flue-eve is an adapter that lets apps written for Eve's
browser-facing API run against a Flue backend.
In practical terms: you keep the Eve authoring and frontend experience —
agent/instructions.md, agent/tools/*, /eve/v1/*, NDJSON streams,
Client, and useEveAgent — while your agent actually runs on Flue's open
runtime.
It exists for teams that like Eve's file-based agent authoring and browser ergonomics but want runtime control: normal Flue agents, Flue tools, Flue deployment targets, and no dependency on Eve's hosted/runtime layer.
- Eve-style
agent/instructions.md,agent/tools/*, andagent/connections/*authoring through scaffold/import /eve/v1/*session routes- NDJSON streaming
Client/ClientSessionuseEveAgentsessionId,continuationToken, andstreamIndex
- It does not reimplement the Eve runtime.
- It does not make Flue pretend to be Eve internally.
- It does not expose Flue stream offsets or runtime internals to browser clients.
The boundary is deliberate: Eve shape at the edge, Flue execution behind it.
Docs: https://doeixd.github.io/flue-eve/docs/
npm install flue-eve @flue/runtime hono
npm install -D @flue/cli- Add
flueEve()to Vite so browser calls to/eve/v1/*are proxied during development. - Run
npx flue-eve initto scaffold the Flue agent, compat sidecar, and app mount. - Build your UI with
useEveAgent()or call the API withClient. - Run Flue locally and set
FLUE_BASE_URL=http://127.0.0.1:3583when you want real agent execution.
flue-eve is the adapter package. @flue/runtime runs the agent, hono hosts
the route tree, and @flue/cli provides flue dev.
Flue requires Node.js 22.19.0 or newer. In this repository, use vp so commands
run on the pinned Node version.
Use the Vite plugin to proxy /eve/v1/*, optionally spawn flue dev, and alias
Eve browser imports during migration.
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { flueEve } from "flue-eve/vite";
export default defineConfig({
plugins: [
react(),
flueEve({
flueRoot: process.cwd(),
}),
],
});In development, the browser can call same-origin /eve/v1/*; the plugin proxies
those requests to the Flue dev server.
Run the CLI to create the standard bridge:
npx flue-eve initThe command generates the Flue agent file, src/flue-eve-shim.ts, and, when
src/app.ts exists, injects the mount call. The generated sidecar looks like
this:
// src/flue-eve-shim.ts
import { eveCompat, resolveAdmissionFromRuntime } from "flue-eve/server";
import type { Hono } from "hono";
export function mountEveCompat(app: Hono): void {
app.route(
"/eve/v1",
eveCompat({
agentName: "assistant",
admission: resolveAdmissionFromRuntime("assistant", {
flueBaseUrl: process.env.FLUE_BASE_URL,
}),
}),
);
}// src/app.ts
import { flue } from "@flue/runtime/routing";
import { Hono } from "hono";
import { mountEveCompat } from "./flue-eve-shim.js";
const app = new Hono();
app.route("/", flue());
mountEveCompat(app);
export default app;Set FLUE_BASE_URL=http://127.0.0.1:3583 to loop back to a running flue dev
server. Without real admission configured, use mock admission for deterministic
local contract tests.
To inspect an existing Eve project before scaffolding, run:
npx flue-eve scan
npx flue-eve scan --strictflue-eve/react provides an Eve-compatible useEveAgent hook.
import { useState } from "react";
import { useEveAgent } from "flue-eve/react";
export function Chat() {
const agent = useEveAgent();
const [message, setMessage] = useState("");
const busy = agent.status === "submitted" || agent.status === "streaming";
return (
<form
onSubmit={(event) => {
event.preventDefault();
if (!message.trim() || busy) return;
void agent.send({ message });
setMessage("");
}}
>
{agent.data.messages.map((item) => (
<article key={item.id}>
<strong>{item.role}</strong>
{item.parts.map((part, index) =>
part.type === "text" ? <p key={index}>{part.text}</p> : null,
)}
</article>
))}
<input value={message} onChange={(event) => setMessage(event.target.value)} />
<button disabled={busy || !message.trim()}>Send</button>
{busy ? <button type="button" onClick={agent.stop}>Stop</button> : null}
</form>
);
}The hook returns { data, status, error, events, session, send, stop, reset }.
Use createEveSessionPersistence() when you want localStorage-backed session
resume.
Use flue-eve/client from scripts, tests, server jobs, or custom UIs.
import { Client } from "flue-eve/client";
const client = new Client({ host: "http://127.0.0.1:5173" });
const session = client.session();
const response = await session.send("Hello");
for await (const event of response) {
console.log(event.type);
}
const result = await (await session.send("Summarize the session")).result();
console.log(result.status, result.message, result.data);Use host: "" for same-origin browser calls. Use a full origin for scripts or
split-origin deployments. The client appends /eve/v1/* paths itself.
Browser / scripts
-> /eve/v1/* Eve HTTP contract, NDJSON
-> @flue-eve/compat-server journal, tokens, mapper, auth
-> @flue/runtime agent harness, tools, durable streams
The Vite plugin integrates. The compat server translates. The event journal is
the sole owner of Eve streamIndex, so reconnects replay Eve events rather than
leaking Flue stream offsets.
Supported:
GET /eve/v1/healthGET /eve/v1/infoPOST /eve/v1/sessionPOST /eve/v1/session/:idGET /eve/v1/session/:id/stream?startIndex=Neve/client-compatibleClientandClientSessioneve/react-compatibleuseEveAgent- HITL
input.requested/inputResponses - OAuth park events
outputSchema/result.completed- Vite, SvelteKit, Nuxt, Nitro, Node, and Cloudflare-oriented integrations
Not a goal for v1:
- Reimplementing the Eve runtime
- Eve's runtime loader as the source of truth; Eve-style
agent/files are supported throughnpx flue-eve initscaffold/import - Eve platform channels such as Slack or Discord
- Exposing Flue stream internals to Eve clients
See the compatibility matrix for the detailed ledger.
The public flue-eve package exposes the main subpaths:
| Import | Purpose |
|---|---|
flue-eve/client |
Eve-compatible TypeScript client |
flue-eve/react |
useEveAgent and session persistence helper |
flue-eve/vite |
Vite plugin |
flue-eve/server |
Web-standard compat handler plus Hono helpers |
flue-eve/server/worker |
Cloudflare Worker app helpers |
flue-eve/connections |
MCP / connection shim |
flue-eve/connections/search |
connection__search support |
flue-eve/connections/connect |
Optional @vercel/connect bridge |
The monorepo also contains lower-level @flue-eve/* packages used by the
aggregator.
| Example | Purpose |
|---|---|
examples/flue-integrated |
Vite UI + Flue app + Eve compat sidecar |
examples/vite-react |
React chat against an Eve-compatible server |
examples/vite-vanilla |
Fetch-based browser client |
examples/cloudflare-eve |
Worker-oriented compat server |
examples/sveltekit-eve |
SvelteKit wrapper |
examples/nuxt-eve |
Nuxt module |
examples/nitro-eve |
Nitro plugin |
Use vp so commands run on the pinned Node version.
git clone https://github.com/doeixd/flue-eve.git
cd flue-eve
npm install -g vite-plus
vp install
vp test
vp exec -- pnpm -r run buildUseful scripts:
pnpm dev:integrated # Vite UI + flue dev + Eve shim
pnpm dev:docs # docs site
pnpm build:docs # static docs export
pnpm smoke:spike # mock HTTP smoke testThe test suite covers the compatibility server, client, React hook, Vite integration, deployment helpers, workflows, channels, and examples.
- Published docs — start here
- DEPLOYMENT.md — production deploy notes
- PLAN.md — implementation plan and invariants
- AGENTS.md — coding-agent onboarding
- flue-eve/ — migration skill for AI coding agents
- Eve docs — compatibility target
- Flue docs — runtime
MIT. Eve-derived test fixtures and ported test files are attributed in
test/ATTRIBUTION.md and remain under Apache-2.0 per
their upstream origin.