# Flue CLI reference

> Commands, flags, defaults, and exit behavior for `flue dev`, `run`, `connect`, `build`, `init`, `add`, `update`, `docs`, and `logs`.

- 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/bin/flue.ts`
- `withastro-flue:packages/cli/src/lib/config.ts`
- `withastro-flue:packages/cli/src/lib/dev.ts`
- `withastro-flue:packages/cli/src/lib/build.ts`
- `withastro-flue:packages/cli/src/lib/env.ts`
- `withastro-flue:packages/cli/package.json`

---

---
title: "Flue CLI reference"
description: "Commands, flags, defaults, and exit behavior for `flue dev`, `run`, `connect`, `build`, `init`, `add`, `update`, `docs`, and `logs`."
---

The `flue` executable ships from `@flue/cli` (`bin/flue.mjs` → `dist/flue.js`) and is the primary interface for configuring, developing, exercising, building, and inspecting Flue applications. Commands share a small set of project flags (`--target`, `--root`, `--output`, `--config`, `--env`) resolved through `flue.config.*` with CLI overrides winning. The `target` field is required everywhere it is needed; there is no implicit default.

## Invocation

```bash
flue [--help | -h | help]
flue [--version | -v]
flue <command> [arguments] [flags]
```

| Top-level flag | Exit code | Behavior |
| --- | --- | --- |
| `--help`, `-h`, `help` | `0` | Print full usage to **stdout**. |
| `--version`, `-v` | `0` | Print package version to **stdout**. |
| Unknown command | `1` | Print usage to **stderr**. |

The bin pre-checks Node.js before loading the compiled CLI. Supported runtimes are Node **≥ 22.18** or **≥ 23.6** (native TypeScript config). `package.json` declares `engines.node` as `>=22.19.0`.

## Shared project flags

These flags apply to `dev`, `run`, `connect`, and `build`. Values from the command line override `flue.config.*`; unspecified fields fall through to the config file, then built-in defaults.

<ParamField body="--target" type="node | cloudflare">
Build and runtime target. Required unless set in `flue.config.ts`. `flue run` and `flue connect` only support `node` at execution time; an explicit `--target cloudflare` is rejected at parse time, and a config-only `target: "cloudflare"` is rejected after resolution.
</ParamField>

<ParamField body="--root" type="path">
Project root. Default: directory containing the discovered config file, or the config search directory (cwd when no `--root` is passed). Relative paths resolve from cwd when passed on the CLI. Source discovery prefers `<root>/.flue`, then `<root>/src`, then `<root>`.
</ParamField>

<ParamField body="--output" type="path">
Build artifact directory. Default: `<root>/dist`. Must not resolve to the project root or source root.
</ParamField>

<ParamField body="--config" type="path">
Explicit `flue.config.{ts,mts,mjs,js,cjs,cts}` path, relative to cwd. Without this flag, the CLI searches the root/search directory using basename priority (`flue.config.ts` first).
</ParamField>

<ParamField body="--env" type="path">
Single alternate `.env`-format file. Default: `<config-base>/.env` when present. The path must exist when explicitly set. Only variables not already set in the shell are applied; shell values always win. Passing more than one `--env` is an error.
</ParamField>

Config discovery for `flue dev` also watches `flue.config.*` files. Editing a watched config restarts the dev supervisor (150 ms debounce); invalid config leaves the supervisor waiting for the next valid change.

## Command summary

| Command | Role | Blocks? |
| --- | --- | --- |
| `flue dev` | Watch-mode local server with rebuild/reload | Yes, until SIGINT/SIGTERM |
| `flue run` | One-shot Node workflow invocation | No |
| `flue connect` | Interactive Node agent-instance session | Yes, until EOF or interrupt |
| `flue build` | Production artifact to `output` | No |
| `flue init` | Write starter `flue.config.ts` | No |
| `flue add` | Fetch/list integration blueprints | No |
| `flue update` | Fetch current blueprint for upgrades | No |
| `flue docs` | List, read, or search bundled docs | No |
| `flue logs` | Replay or follow workflow-run events | Follow mode blocks until `run_end` or interrupt |

---

## `flue dev`

Long-running watch-mode development server. Builds the project, serves it locally, watches files, and reloads after relevant changes.

```bash
flue dev [--target <node|cloudflare>] [--root <path>] [--output <path>] [--config <path>] [--port <number>] [--env <path>]
```

<ParamField body="--port" type="number">
Local server port. Default: **3583** (`DEFAULT_DEV_PORT`).
</ParamField>

<Tabs>
<Tab title="Node">

Builds `server.mjs` to `output`, spawns it as a child process, and respawns after every successful rebuild. Env-file changes on Node trigger a forced reload even when build output is unchanged.

</Tab>
<Tab title="Cloudflare">

Runs Vite with the official Cloudflare Workers plugin. Only structural source changes (agents, workflows, channels, `app.ts`, `cloudflare.ts`, Wrangler config) trigger rebuilds. Runtime bindings continue to use `.dev.vars`, `.env`, and `CLOUDFLARE_ENV`.

</Tab>
</Tabs>

Rebuilds are debounced 150 ms. Rebuild errors are logged but do not exit the dev loop.

**Exit behavior:** `SIGINT` → `130`, `SIGTERM` → `143`. Config watcher failure → `1`. Unexpected child exit (non-restart) → child exit code or `1`. Initial build failure → `1`.

<RequestExample>

```bash
flue dev --target node
flue dev --target cloudflare --port 8787
flue dev --env .env.staging
```

</RequestExample>

---

## `flue run`

One-shot Node workflow invocation: silent build → spawn local IPC child → invoke workflow → exit. Does not publish HTTP run-inspection routes; use `flue logs` only for runs owned by a running server.

```bash
flue run <workflow> [--target node] [--payload <json>] [--root <path>] [--output <path>] [--config <path>] [--env <path>]
```

| Argument | Required | Description |
| --- | --- | --- |
| `<workflow>` | Yes | Discovered workflow module name (basename under `workflows/`). |

<ParamField body="--payload" type="JSON string" default="{}">
Workflow input payload. Must be valid JSON; validated at parse time.
</ParamField>

**Output:** Build banner and streamed events on **stderr**. Non-null workflow result as formatted JSON on **stdout**.

**Exit behavior:** Success → `0`. Workflow or build failure → `1`. `SIGINT`/`SIGTERM` → `130`/`143`. Local process readiness timeout is 60 seconds.

Cloudflare targets are unsupported. The CLI prints a curl example against `http://localhost:3583/workflows/<workflow>` and exits `1`.

<RequestExample>

```bash
flue run hello --target node
flue run summarize --payload '{"text":"hello"}' --env .env.staging
```

</RequestExample>

---

## `flue connect`

Builds a Node project and opens an interactive local connection to one agent instance. Enter one prompt per line; Ctrl+D closes the session.

```bash
flue connect <agent> <instance-id> [--target node] [--root <path>] [--output <path>] [--config <path>] [--env <path>]
```

| Argument | Required | Description |
| --- | --- | --- |
| `<agent>` | Yes | Discovered agent module name. |
| `<instance-id>` | Yes | Agent instance identifier (for example `local` or a thread ID). |

`--payload` is rejected; enter prompts interactively after connecting.

**Output:** Connection status and streamed events on **stderr**. Non-null prompt results as JSON on **stdout**.

**Exit behavior:** Build or initial connection failure → `1`. Prompt errors log to stderr but keep the session open. Unexpected child exit before EOF → `exitCode 1`. Normal EOF → `0`. `SIGINT`/`SIGTERM` → `130`/`143`.

Cloudflare targets are unsupported at parse and resolution time.

<RequestExample>

```bash
flue connect assistant customer-123 --target node
flue connect assistant customer-123 --env .env.staging
```

</RequestExample>

---

## `flue build`

Discover agents, workflows, channels, and optional `app.ts` / `db.ts` / `cloudflare.ts` entries, then write target-specific deployment output.

```bash
flue build [--target <node|cloudflare>] [--root <path>] [--output <path>] [--config <path>] [--env <path>]
```

| Target | Primary output |
| --- | --- |
| `node` | `<output>/server.mjs` (Vite SSR bundle) |
| `cloudflare` | Workers-compatible build via Cloudflare Vite integration |

Build fails with exit `1` when no agent or workflow modules are discovered, when `target` is missing, or when `output` equals the project or source root.

<RequestExample>

```bash
flue build --target node
flue build --target cloudflare --root ./my-app
flue build --target node --output ./build
```

</RequestExample>

---

## `flue init`

Write a starter `flue.config.ts`. Does not scaffold agents, workflows, or application code.

```bash
flue init --target <node|cloudflare> [--root <path>] [--force]
```

<ParamField body="--target" type="node | cloudflare" required>
Written into the generated config as `target: '<value>'`.
</ParamField>

<ParamField body="--root" type="path" default="cwd">
Existing directory to receive `flue.config.ts`. Must exist.
</ParamField>

<ParamField body="--force" type="boolean" default="false">
Overwrite when any `flue.config.*` already exists in the target directory. If `--force` writes `flue.config.ts` beside another variant, the new `.ts` file takes precedence; the older file remains on disk with a warning.
</ParamField>

**Exit behavior:** Success → `0`. Missing `--target`, existing config without `--force`, missing target directory, or write failure → `1`.

<ResponseExample>

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

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

</ResponseExample>

---

## `flue add` and `flue update`

Fetch Markdown implementation blueprints from `https://flueframework.com/cli/blueprints` (overridable via `FLUE_REGISTRY_URL`). Neither command installs packages or edits project files.

```bash
flue add [<kind> <name|url>] [--print]
flue update <kind> <name|url> [--print]
```

| Kind | Produces |
| --- | --- |
| `sandbox` | Sandbox adapter |
| `channel` | Channel integration |
| `database` | Database persistence adapter |
| `tooling` | Developer tooling integration |

`flue add` with no arguments lists known blueprints on **stderr** and exits `0`. `flue update` requires both `<kind>` and `<name|url>`.

<ParamField body="--print" type="boolean">
Force raw blueprint Markdown to **stdout**, bypassing agent-detection heuristics (`@vercel/detect-agent`).
</ParamField>

**Output modes:** In agent mode (`--print` or detected coding agent), blueprint Markdown goes to **stdout**. Otherwise, human-oriented pipe instructions go to **stderr**.

**Exit behavior:** Success → `0`. Unknown kind, unknown named blueprint, registry HTTP error, or network failure → `1`. `flue update` rejects missing arguments at parse time → `1`.

<RequestExample>

```bash
flue add
flue add channel slack --print | codex
flue add sandbox https://e2b.dev --print | claude
flue update channel slack --print | codex
```

</RequestExample>

---

## `flue docs`

Browse documentation bundled inside the installed `@flue/cli` package. No network access required.

```bash
flue docs
flue docs read <path>
flue docs search <query>
```

| Subcommand | stdout | stderr |
| --- | --- | --- |
| (none) | Page catalog (`path` + `title`) | Usage header |
| `read <path>` | Markdown page body | — |
| `search <query>` | JSON `{ query, results }` (max 8 hits) | Read hint |

`read` accepts page paths (`guide/sandboxes`), website paths (`/docs/guide/sandboxes/`), and full URLs. Unknown pages exit `1`.

**Exit behavior:** Success → `0`. Missing bundled docs tree, unknown page, or invalid subcommand → `1`.

<RequestExample>

```bash
flue docs
flue docs read guide/sandboxes
flue docs search "durable execution"
```

</RequestExample>

---

## `flue logs`

Read-only inspection of workflow-run events from a running Flue server via the Durable Streams protocol. Does not invoke work.

```bash
flue logs <workflowRunId> [--server <url>] [--header 'Name: value'] [--follow|-f|--no-follow] [--since <offset>] [--types <a,b,c>] [--limit <n>] [--format <pretty|ndjson>]
```

| Argument | Required | Description |
| --- | --- | --- |
| `<workflowRunId>` | Yes | Opaque run ID (for example `run_01H...`). |

<ParamField body="--server" type="URL" default="http://127.0.0.1:3583">
Base URL of the running Flue server hosting `/runs/<runId>`.
</ParamField>

<ParamField body="--header" type="Name: value" multiple>
Repeatable curl-style HTTP header. Duplicate names and the reserved `Accept` header are rejected.
</ParamField>

<ParamField body="--follow / -f / --no-follow" type="boolean">
Follow mode control. When neither is set, the CLI probes `GET /runs/<runId>?meta`: **active** runs are followed, **terminal** runs replay once.
</ParamField>

<ParamField body="--since" type="offset" default="-1 (beginning)">
Resume strictly after a Durable Streams offset. NDJSON output includes per-event `offset` derived from `eventIndex`.
</ParamField>

<ParamField body="--types" type="comma-separated list">
Client-side event-type filter.
</ParamField>

<ParamField body="--limit" type="positive integer">
Cap emitted events (client-side, both modes).
</ParamField>

<ParamField body="--format" type="pretty | ndjson" default="pretty">
`pretty` renders human-readable events on **stderr**; `ndjson` writes one JSON object per **stdout** line.
</ParamField>

**Exit behavior:**

| Condition | Exit code |
| --- | --- |
| Success (no failing `run_end`) | `0` |
| Request or fetch failure | `1` |
| Stream interrupted (non-signal) | `1` |
| Consumed `run_end` with `isError: true` | `2` |
| Ctrl+C during follow mode | `130` |

<RequestExample>

```bash
flue logs run_01H...
flue logs run_01H... --no-follow
flue logs run_01H... --types tool,log,run_end --format ndjson
flue logs run_01H... --server https://api.example.com --header "Authorization: Bearer $TOKEN"
```

</RequestExample>

---

## Exit code reference

| Code | Meaning |
| --- | --- |
| `0` | Command completed successfully. |
| `1` | Parse/validation error, config resolution failure, build failure, workflow/agent failure, registry or docs error, stream interruption, or unexpected process exit. |
| `2` | `flue logs` observed a failing `run_end` event. |
| `130` | `SIGINT` (Ctrl+C) — `dev`, `run`, `connect`, `logs` follow mode. |
| `143` | `SIGTERM` — `dev`, `run`, `connect`. |

Commands other than `dev` and `flue logs` follow mode install `SIGINT`/`SIGTERM` handlers that terminate any spawned local IPC child before exiting.

## Typical workflow

<Steps>
<Step title="Initialize and configure">

```bash
flue init --target node
```

Set `target`, `root`, and `output` in `flue.config.ts` or pass flags per command.

</Step>
<Step title="Develop locally">

```bash
flue dev
```

Exercise HTTP routes, or use `flue connect` / `flue run` for private local execution on Node.

</Step>
<Step title="Inspect and ship">

```bash
flue logs run_01H...          # runs from the dev server
flue build --target node      # production artifact
```

</Step>
</Steps>

## Related pages

<CardGroup>
<Card title="Installation" href="/installation">
Prerequisites, package managers, and first-install commands for Flue projects.
</Card>
<Card title="Flue quickstart" href="/flue-quickstart">
Scaffold, `flue dev`, `flue run`, and `flue connect` in one walkthrough.
</Card>
<Card title="Flue configuration reference" href="/flue-configuration-reference">
`flue.config.*` keys, source-root precedence, and CLI override rules.
</Card>
<Card title="Flue HTTP API reference" href="/flue-http-api-reference">
Routes mounted by `flue dev` and production servers that `flue logs` reads.
</Card>
<Card title="Flue workflows" href="/flue-workflows">
Author workflows and interpret run events.
</Card>
<Card title="Flue deploy" href="/flue-deploy">
Target selection, `flue build` output, and deployment paths.
</Card>
</CardGroup>
