> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hitheo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Project Config

> Use theo.config.json to pin a persona, default skills, and inline tools for every MCP call in a repo.

When `@hitheo/mcp` starts, it looks for a `theo.config.json` in the working directory (the IDE workspace root). If it finds one, every relevant tool call is enriched with the values you defined — your IDE agent doesn't have to remember to pass them.

This is how you give a repo its own persona ("you are a backend engineer for this Express API"), pre-activate the skills that matter for the project, and expose custom tools that only make sense in this codebase.

<Tip>
  Most people generate this file with `theo init`, then tune `persona` and `skills` by hand. You rarely need to write it from scratch.
</Tip>

## Quick example

```json theme={null}
{
  "persona": "You are a backend engineer assistant for this Express API.",
  "skills": ["deep-research", "content-writer"],
  "defaultMode": "code",
  "temperature": 0.3,
  "tools": [
    {
      "name": "check_stock",
      "description": "Look up current stock levels for a SKU",
      "input_schema": {
        "type": "object",
        "properties": { "sku": { "type": "string" } },
        "required": ["sku"]
      }
    }
  ],
  "metadata": { "team": "warehouse-ops" }
}
```

Drop that at the repo root. The next time any MCP tool fires, those fields are merged into the request.

## Schema

| Field         | Type                               | Used by         | Description                                                                                     |
| ------------- | ---------------------------------- | --------------- | ----------------------------------------------------------------------------------------------- |
| `persona`     | `string`                           | `theo_complete` | Custom system prompt injected as `persona.system_prompt`.                                       |
| `skills`      | `string[]`                         | `theo_complete` | Skill slugs to activate on every completion.                                                    |
| `defaultMode` | [`ChatMode`](/sdk-reference/types) | `theo_complete` | Fallback mode when the caller didn't pass one.                                                  |
| `tools`       | `ToolDef[]`                        | `theo_complete` | Inline tool definitions Theo can call during the agent loop.                                    |
| `temperature` | `number`                           | reserved        | Default temperature. *(Plumbed in the config loader but not yet forwarded by `theo_complete`.)* |
| `metadata`    | `Record<string, unknown>`          | reserved        | Metadata attached to every request for tracking. *(Loaded today; passthrough planned.)*         |

`ToolDef` shape (used in `tools`):

```ts theme={null}
interface ToolDef {
  name: string;
  description: string;
  input_schema?: Record<string, unknown>;  // JSON-Schema
}
```

## File precedence and sandbox

`@hitheo/mcp` loads config in this order, by design:

1. **`theo.config.json`** — always loaded if present. Parsed with `JSON.parse`; no code runs.
2. **`theo.config.js` / `theo.config.ts`** — **ignored** unless you opt in. Loading them would `import()` arbitrary code from the workspace root, which is unsafe when an IDE spawns the MCP server inside a project you haven't audited.

To opt back in:

```bash theme={null}
export THEO_ALLOW_JS_CONFIG=1
```

With that flag set, the loader tries `theo.config.js` first, then `theo.config.ts`, before falling back to JSON. If a JS/TS config is present without the flag, the server logs a warning to stderr and skips it.

<Warning>
  Only set `THEO_ALLOW_JS_CONFIG=1` in directories you authored or trust. A malicious `theo.config.js` in any repo you open will execute as your user the moment the IDE launches the MCP server.
</Warning>

Even with the flag set, `theo.config.json` remains the recommended format. The TypeScript helper `defineConfig` from [`@hitheo/sdk`](/sdk-reference/project-config) can emit a typed object you then `JSON.stringify` into the JSON file if you want autocompletion in your editor.

## Merge semantics

When the MCP server handles a tool call, the project config is *merged* with the arguments the IDE agent passes in. The rules:

| Field                     | Merge rule                                                                                    |
| ------------------------- | --------------------------------------------------------------------------------------------- |
| `persona`                 | If config has `persona`, it becomes `persona.system_prompt`. Caller arg overrides if present. |
| `skills`                  | Concatenated: `[...config.skills, ...args.skills]`. Empty result → field omitted.             |
| `defaultMode`             | Only used if the caller didn't pass `mode`. Caller args win.                                  |
| `tools`                   | Forwarded as-is when no caller args; not currently overridden by per-call tool lists.         |
| `temperature`, `metadata` | Loaded by the config parser; not yet forwarded by `theo_complete`.                            |

In practice this means:

* A repo persona is always applied.
* Skills are **additive** — the agent can request more skills on top of the repo's defaults, but cannot subtract from them in a single call.
* Modes follow "explicit wins": if the agent passes `mode: "research"`, that beats `defaultMode: "code"`.

## Where `theo init` puts it

When you run `theo init`, the CLI writes a starter config based on your folder name:

```json theme={null}
{
  "persona": "You are an AI assistant for the <project-name> project.",
  "skills": [],
  "defaultMode": "auto"
}
```

You can edit it freely afterward; the MCP server will pick up changes the next time it starts (i.e. the next IDE restart).

## Updating without restarts

The config is read **once at server startup**, so changes take effect on the next MCP server boot (which usually means the next time your IDE reopens the workspace). If you need to iterate on a persona quickly, edit `.theo/RULES.md` instead — it influences how the IDE's agent thinks about the tools, and most agents reload it automatically.

## Related

* **[Install](/mcp/install)** — how `theo init` writes the config file in the first place.
* **[SDK `defineConfig`](/sdk-reference/project-config)** — typed helper for projects that prefer TS authoring.
* **[Skills overview](/skills/overview)** — what to put in `skills`.
* **[Security](/mcp/security)** — full rationale for the JSON-only default.
