# Flue configuration reference

> `flue.config.*` keys (`target`, `root`, `output`), source-root precedence, env loading, and CLI override rules.

- Repository: withastro/flue-with-vercel-eve
- GitHub: https://github.com/withastro/flue
- Human docs: https://grok-wiki.com/public/docs/withastro-flue-with-vercel-eve-f4b79875fff6
- Complete Markdown: https://grok-wiki.com/public/docs/withastro-flue-with-vercel-eve-f4b79875fff6/llms-full.txt

## Source Files

- `withastro-flue:packages/cli/src/lib/config.ts`
- `withastro-flue:packages/cli/src/lib/config-paths.ts`
- `withastro-flue:packages/cli/src/lib/source-root.ts`
- `withastro-flue:examples/hello-world/flue.config.ts`
- `withastro-flue:examples/react-chat/flue.config.ts`
- `withastro-flue:packages/cli/src/lib/env.ts`

---

---
title: "Flue configuration reference"
description: "`flue.config.*` keys (`target`, `root`, `output`), source-root precedence, env loading, and CLI override rules."
---

`flue.config.{ts,mts,mjs,js,cjs,cts}` is the build-time configuration surface for the Flue CLI. It selects the deployment target, project root, and build output directory. Runtime concerns—provider registration, model selection, and platform bindings—belong in `app.ts`, not in the config file.

## Authoring API

Import `defineConfig` from `@flue/cli/config` for type checking and editor completion:

```ts title="flue.config.ts"
import { defineConfig } from '@flue/cli/config';

export default defineConfig({
  target: 'node',
  output: 'dist/server',
});
```

<ParamField body="defineConfig(config)" type="UserFlueConfig">
Returns the configuration unchanged. Provides TypeScript types for `flue.config.ts` authoring.
</ParamField>

The public `@flue/cli/config` subpath exports `defineConfig`, `UserFlueConfig`, and `FlueConfig`. Config discovery and resolution are internal to the CLI.

<Note>
TypeScript config files load through Node's native dynamic `import()` with type-stripping. Use erasable TypeScript only—no `enum`, runtime `namespace`, parameter properties, or decorators. Plain `.js` / `.mjs` / `.cjs` variants are also supported.
</Note>

## Configuration file discovery

When no `--config` flag is passed, the CLI scans the search directory for the first matching basename:

| Priority | Basename |
| --- | --- |
| 1 | `flue.config.ts` |
| 2 | `flue.config.mts` |
| 3 | `flue.config.mjs` |
| 4 | `flue.config.js` |
| 5 | `flue.config.cjs` |
| 6 | `flue.config.cts` |

The search directory defaults to the process working directory. Passing `--root <path>` changes the search directory to that path (after resolving it to an absolute path from `cwd`).

<ParamField body="--config <path>" type="string">
Select an explicit config file. The path resolves relative to `cwd`, not `--root`. The file must exist; a missing path throws immediately.
</ParamField>

If no config file is found and no inline values supply required fields, resolution fails with a clear error.

## Config keys

Only three keys are accepted. The schema is strict—unknown fields are rejected at load time.

### `target`

<ParamField body="target" type="'node' | 'cloudflare'">
Build and development target. Required unless supplied via `--target`.
</ParamField>

| Value | Behavior |
| --- | --- |
| `'node'` | Builds a Node.js server artifact. |
| `'cloudflare'` | Builds a Workers-compatible application. |

There is no default. Omitting `target` from both the config file and CLI flags produces:

```
[flue] Missing required `target`. Set it via `--target <node|cloudflare>` or in `flue.config.ts` as `target: "node"` (or `"cloudflare"`).
```

### `root`

<ParamField body="root" type="string">
Project root. Must not be empty. Defaults to the directory containing the loaded config file, or the search directory when no config file exists.
</ParamField>

Relative `root` values in a config file resolve from the directory containing that file. Relative values passed via `--root` resolve from `cwd`. Absolute paths are used as-is.

The resolved `root` is always an absolute path in the internal `FlueConfig` object.

### `output`

<ParamField body="output" type="string">
Build output directory. Must not be empty. Defaults to `<root>/dist`.
</ParamField>

Relative `output` values in a config file resolve from the directory containing that file—not from `root`. Relative values passed via `--output` resolve from `cwd`.

<Warning>
`output` must not resolve to the project `root` or the derived `sourceRoot`. Setting output to either location throws:

```
[flue] `output` resolves to the project root (…) / source root (…). Build artifacts must go in a separate directory, e.g. `dist/`.
```
</Warning>

## Resolved configuration

After discovery, validation, and merging, the CLI produces a `FlueConfig` object consumed by `dev`, `build`, `run`, and `connect`:

<ResponseField name="FlueConfig" type="object">
Fully resolved configuration with absolute paths.
</ResponseField>

| Field | Type | Source |
| --- | --- | --- |
| `target` | `'node' \| 'cloudflare'` | Config file or `--target` |
| `root` | `string` (absolute) | Config file, `--root`, or default |
| `sourceRoot` | `string` (absolute) | Derived from `root` (see below) |
| `output` | `string` (absolute) | Config file, `--output`, or `<root>/dist` |

`sourceRoot` is not authored in `flue.config.*`. The CLI derives it from `root`.

## Source-root precedence

Flue discovers agents, workflows, channels, and `app.ts` from `sourceRoot`, not from `root` directly. Given a resolved `root`, the CLI picks the first existing directory:

```
1. <root>/.flue/
2. <root>/src/
3. <root>/
```

When both `.flue/` and `src/` exist, `.flue/` wins. Bare-layout directories at `root` (for example `agents/`, `workflows/`) are ignored when `.flue/` is present.

<Info>
Use `.flue/` for generated or scaffolded layouts. Use `src/` for conventional TypeScript project structure. Use `root` directly only when neither subdirectory exists.
</Info>

## Merge and precedence

Configuration merges per field on a flat surface—there are no nested objects to deep-merge.

```
CLI flags (--target, --root, --output)
        ↓ overrides
flue.config.* file values
        ↓ overrides
Built-in defaults (root, output only)
```

| Field | Default when unset everywhere |
| --- | --- |
| `target` | Error—no default |
| `root` | Config-file directory, or search directory |
| `output` | `<root>/dist` |

CLI flags always win over config-file values for the field they set. Omitting a CLI flag falls through to the file value, then the default.

### Path resolution summary

| Value source | Relative path resolves from |
| --- | --- |
| `root` / `output` in config file | Directory containing the config file |
| `--root` / `--output` on CLI | Process `cwd` |
| `--config <path>` | Process `cwd` |
| Auto-discovery scan | `--root` if set, else `cwd` |

## Environment loading

Commands `flue dev`, `flue build`, `flue run`, and `flue connect` load environment variables before resolving configuration. `flue init`, `flue add`, `flue update`, `flue docs`, and `flue logs` do not use this path.

### Env file selection

The env base directory is the config-file directory when a config file is found, otherwise the search directory (`--root` or `cwd`).

<ParamField body="--env <path>" type="string">
Select one alternate `.env`-format file. Relative paths resolve from the env base directory. The file must exist when explicitly specified.
</ParamField>

Without `--env`, the CLI attempts `<env-base>/.env`. If that file does not exist, env loading is a no-op.

Passing `--env` more than once is an error.

### Precedence

Shell environment wins over file values. The env loader only sets variables that were **not** already defined in `process.env` when the loader was created:

1. Existing shell / process environment (highest)
2. Keys from the selected `.env` file (fill gaps only)

Env is applied before the config module loads, so `process.env` references inside `flue.config.ts` can read file-provided values that the shell did not already set.

### Cloudflare builds

For `target: 'cloudflare'`, the build step additionally loads Vite env prefixes (`CLOUDFLARE_`, `WRANGLER_HYPERDRIVE_LOCAL_CONNECTION_STRING_`) from the project root during the build. Local Cloudflare development continues to follow Wrangler conventions for `.dev.vars`, `.env`, and `CLOUDFLARE_ENV`.

## CLI override flags

These flags apply to `flue dev`, `flue build`, `flue run`, and `flue connect`:

| Flag | Config key | Effect |
| --- | --- | --- |
| `--target <node\|cloudflare>` | `target` | Override or supply required target |
| `--root <path>` | `root` | Override project root; also changes config search directory |
| `--output <path>` | `output` | Override build output directory |
| `--config <path>` | — | Select config file (relative to `cwd`) |
| `--env <path>` | — | Select env file (relative to env base directory) |

`flue dev` adds `--port <number>` (default `3583`), which is not a `flue.config.*` key.

`flue init` writes a starter `flue.config.ts` with `--target` (required), `--root`, and `--force`. It does not read env files or merge existing config values.

## What does not belong in `flue.config.*`

Build-time config covers target, root, and output only. Keep runtime registration in application code:

| Concern | Location |
| --- | --- |
| Provider / model registration | `app.ts` via `registerProvider(...)` |
| Agent model defaults | `createAgent(() => ({ model: "…" }))` |
| API keys and secrets | Environment variables or platform bindings |
| HTTP routes and middleware | `app.ts` composition |

Examples in the repository intentionally leave `target` unset so `flue dev --target node` and `flue dev --target cloudflare` work without editing the config file.

## Validation errors

| Condition | Result |
| --- | --- |
| No `target` in file or CLI | `Missing required 'target'` |
| Unknown config field | `Invalid config in …` with field path |
| Invalid `target` value | `Invalid config in …` |
| Empty `root` or `output` | `Path must not be empty.` |
| `output` equals `root` or `sourceRoot` | `output resolves to the project root / source root` |
| Default export is not an object | `must export a config object as the default export` |
| Explicit `--config` path missing | `Config file not found: …` |
| Explicit `--env` path missing | `--env points at a path that doesn't exist` |
| Unsupported TypeScript syntax in config | Hint to use erasable types or plain JS |

## Examples

<CodeGroup>

```ts title="Minimal Node target"
import { defineConfig } from '@flue/cli/config';

export default defineConfig({
  target: 'node',
});
```

```ts title="Custom output directory"
import { defineConfig } from '@flue/cli/config';

export default defineConfig({
  target: 'node',
  output: 'dist/server',
});
```

```ts title="Defer target to CLI"
import { defineConfig } from '@flue/cli/config';

export default defineConfig({});
```

</CodeGroup>

<RequestExample>

```bash
# Override config-file values for one invocation
flue build --target cloudflare --root ./my-app --output ./build

# Staging credentials without editing the config file
flue run summarize --target node --env .env.staging

# Config outside the project root
flue dev --config ../shared/flue.config.ts
```

</RequestExample>

## Related pages

<CardGroup>
<Card title="Flue project layout" href="/flue-project-layout">
Source-root resolution, agent and workflow module placement, and discovery boundaries.
</Card>
<Card title="Flue CLI reference" href="/flue-cli-reference">
Command flags, defaults, and exit behavior for all `flue` subcommands.
</Card>
<Card title="Flue deploy" href="/flue-deploy">
Target-specific build artifacts and deployment integration.
</Card>
<Card title="Flue quickstart" href="/flue-quickstart">
End-to-end workflow from scaffold through `flue dev` and `flue run`.
</Card>
</CardGroup>
