docs/developers/daemon/00-index.md
This is the developer-facing technical documentation for qwen-code daemon mode: the qwen serve HTTP daemon, the @qwen-code/acp-bridge package, the workspace-scoped MCP transport pool, multi-client permission mediation, typed daemon event schema v1, the TypeScript SDK daemon client, and the adapters that connect to the daemon.
It complements, rather than replaces, these existing docs:
| Existing doc | Audience | Source of truth for |
|---|---|---|
../../users/qwen-serve.md | Operators | User quickstart, flags, threat model |
../qwen-serve-protocol.md | Protocol implementers | HTTP route catalog, request/response shapes, error codes |
../examples/daemon-client-quickstart.md | SDK users | End-to-end TypeScript walkthrough |
../daemon-client-adapters/ | Adapter authors | Legacy client adapter design docs |
14-cli-tui-adapter.md | Adapter authors | Client adapter design notes |
../../design/f2-mcp-transport-pool.md | F2 maintainers | Workspace MCP transport pool design v2.2 |
If you want to start a daemon and use it, read qwen-serve.md first. If you want to build a client against the wire format, read qwen-serve-protocol.md. If you want to understand, extend, or debug the daemon internals, read this set.
Pick the path that matches your goal:
20 -> 17 -> 19.01 -> 02 -> 03 -> 08 -> 09 -> 10 -> 11 -> 12.01 -> 09 -> 10 -> 13 -> (14 / 15 / 16).01 -> 03 -> 05 -> 06.01 -> 03 -> 04 -> 12.19 -> 18 -> 17 -> 20.01-architecture.md - system architecture, process topology, package map, and all seven top-level sequence diagrams.02-serve-runtime.md - runQwenServe bootstrap, Express app, middleware chain, graceful shutdown.03-acp-bridge.md - @qwen-code/acp-bridge package internals, session multiplexing, channel factory, ACP child spawn.04-permission-mediation.md - MultiClientPermissionMediator, four policies, N1 timeout invariant, cancel sentinel.05-mcp-transport-pool.md - McpTransportPool (F2), pool entries, reverse index, restart, drain.06-mcp-budget-guardrails.md - WorkspaceMcpBudget, modes (off/warn/enforce), hysteresis, refused-batch coalescing.07-workspace-filesystem.md - WorkspaceFileSystem sandbox, path policy, audit, BridgeFileSystem contract.08-session-lifecycle.md - create / attach / load / resume, X-Qwen-Client-Id, heartbeat, eviction, metadata.09-event-schema.md - typed event schema v1: all 53 known event types with payloads, reducers, forward compatibility.10-event-bus.md - EventBus, monotonic IDs, ring replay, Last-Event-ID, slow-client backpressure, client_evicted.11-capabilities-versioning.md - capability registry, protocol version, schema version, conditional advertisement.12-auth-security.md - bearer middleware, host allowlist, CORS deny, mutation gate, --require-auth, /health exemption, device flow.13-sdk-daemon-client.md - TypeScript SDK: DaemonClient, DaemonSessionClient, DaemonAuthFlow, SSE parser, event reducers, ui/* transcript layer.14-cli-tui-adapter.md - shared UI transcript layer and the legacy CLI TUI daemon adapter relationship.15-channel-adapters.md - DaemonChannelBridge shared base plus DingTalk, WeChat (Weixin), Telegram, Feishu per-channel adapters.16-vscode-ide-adapter.md - DaemonIdeConnection, loopback-only enforcement, webview bridging.17-configuration.md - env vars, CLI flags, settings.json keys that affect the daemon.18-error-taxonomy.md - typed errors per layer with remediation.19-observability.md - QWEN_SERVE_DEBUG, debugging recipes, telemetry gaps.20-quickstart-operations.md - shortest startup path, curl checks, route map, and embedded invocation recipes.qwen --acp child that hosts one workspace's agent runtime. Production attempts to preheat the trusted primary child for compatibility; trusted secondaries start on their first runtime command or Session, and untrusted secondaries do not start ACP. Legacy primary routes retain their existing compatibility behavior. The owning bridge multiplexes sessions and clients onto that child.@qwen-code/acp-bridge package (packages/acp-bridge/). Owns session multiplexing, the permission mediator, the event bus, and the channel factory.packages/acp-bridge/src/bridgeClient.ts. Wraps one ACP ClientSideConnection, and handles requestPermission, sendPrompt, and cancelSession.spawnChannel runs qwen --acp as a subprocess; inMemoryChannel runs it in-process for tests.packages/sdk-typescript/src/daemon/DaemonClient.ts. The TypeScript SDK HTTP-level facade over the daemon.packages/sdk-typescript/src/daemon/DaemonSessionClient.ts. Session-scoped wrapper that tracks lastSeenEventId for SSE replay.packages/acp-bridge/src/eventBus.ts. Per-session in-memory pub/sub with monotonic IDs, a bounded ring, and per-subscriber backpressure.BridgeFileSystem. F2: workspace-scoped MCP transport pool. F3: multi-client permission mediation. F4: protocol completion and daemon client surfaces.packages/core/src/tools/mcp-transport-pool.ts. F2 workspace-scoped pool sharing one MCP transport per server name and config fingerprint.first-responder, designated, consensus, or local-only. Decides how multi-client permission votes resolve.X-Qwen-Client-Id of the client that initiated the prompt currently requesting permission. The designated policy only accepts votes from this id.packages/core/src/tools/mcp-pool-entry.ts. One entry in McpTransportPool: one MCP transport, a refcount of attached sessions, and an idle drain timer.single (one ACP session shared by all clients) or thread (one session per conversation thread). The default is single.GET /session/:id/events).workspaceCwd is the legacy primary default; workspaces[] is the catalog of isolated runtimes and their trust/removal metadata.Use these anchors when moving from the docs into the latest main code:
| Surface | Implementation anchors | Primary docs |
|---|---|---|
| Bootstrap and HTTP assembly | packages/cli/src/serve/run-qwen-serve.ts, packages/cli/src/serve/server.ts, packages/cli/src/serve/routes/health.ts, packages/cli/src/serve/web-shell-static.ts | 02, 20 |
| ACP bridge and session multiplexing | packages/acp-bridge/src/bridge.ts, packages/acp-bridge/src/bridgeTypes.ts, @qwen-code/acp-bridge | 03, 08 |
| Permission mediation | packages/acp-bridge/src/permissionMediator.ts, fromLoopback: boolean, policy.* | 04, 12 |
| MCP transport pool | packages/core/src/tools/mcp-transport-pool.ts, mcp-pool-key.ts, pid-descendants.ts, session-mcp-view.ts, /mcp refresh, MCPCallInterruptedError | 05, 06 |
| MCP budget guardrails | packages/core/src/tools/mcp-workspace-budget.ts, ServeMcpBudgetStatusCell.scope, budgets[] | 06 |
| Workspace filesystem | packages/cli/src/serve/fs/, assertTrustedForIntent(trusted, intent), meta.matchedIgnore, includeIgnored | 07 |
| Event schema and SSE writer | packages/sdk-typescript/src/daemon/events.ts, packages/cli/src/serve/routes/sse-events.ts, formatSseFrame, packages/cli/src/acp-integration/session/emitters/tool-call-emitter.ts, ToolCallEmitter.resolveToolProvenance, tool_call.provenance, serverId | 09, 10 |
| Event resync | state_resync_required, awaitingResync, RESYNC_PASSTHROUGH_TYPES, asKnownDaemonEvent, unrecognizedKnownEventCount | 09, 10 |
| Capabilities | packages/cli/src/serve/capabilities.ts, mcp_server_restart_refused.reason, MCP_RESTART_REFUSED_REASONS.has | 11 |
| Auth and device flow | packages/cli/src/serve/auth.ts, packages/cli/src/serve/auth/device-flow.ts | 12 |
| TypeScript SDK daemon client | packages/sdk-typescript/src/daemon/{DaemonClient,DaemonSessionClient,DaemonAuthFlow,sse,events,types}.ts, MCP_RESTART_DEFAULT_TIMEOUT_MS | 13 |
| Shared UI transcript layer | DaemonUiEventType, DaemonSessionProvider, packages/webui/src/daemon/ | 13, 14, ../daemon-ui/README.md |
| Channels and IDE adapters | packages/channels/, packages/vscode-ide-companion/src/services/daemonIdeConnection.ts | 15, 16 |
docs/developers/daemon-ui/ and adapter design notes.packages/zed-extension/) - it launches qwen --acp over stdio directly and bypasses the daemon.--no-http-bridge still falls back to http-bridge today; a stable in-process serve mode would need new docs when it lands.| Area | Current state | Primary docs |
|---|---|---|
| Bootstrap / listen path | qwen serve lazy-loads runQwenServe, validates auth/workspace/budget/settings, builds an Express app, then calls app.listen and blocks forever until signal. | 02, 20 |
| Auth / network guardrails | Token-less loopback grants the primary listener local operator authority; non-loopback requires bearer; --require-auth extends bearer to loopback and /health; Host allowlist and default CORS deny are active. | 12, 17 |
| Session lifecycle | POST /session, load, resume, metadata patch, heartbeat, eviction, idle reaping, prompt pending limits, and graceful close are documented. | 08, 10 |
| ACP bridge | Single ACP child multiplexed by default; sessionScope supports single and thread; BridgeFileSystem, context filename, env overrides, and channel idle timeout are wired. | 03, 07 |
| MCP pool / budget | Workspace MCP pool is on by default unless QWEN_SERVE_NO_MCP_POOL=1; guardrail events and restart semantics are documented. | 05, 06 |
| Permissions | F3 mediator supports first-responder, designated, consensus, and local-only; invalid settings fail explicitly. | 04, 12 |
| Area | Current state | Primary docs |
|---|---|---|
| HTTP routes | The route catalog lives in qwen-serve-protocol.md; this daemon set only references it and explains implementation ownership. | ../qwen-serve-protocol.md, 20 |
| Event schema | EVENT_SCHEMA_VERSION = 1; 53 known event types; id-less subscriber synthetic frames; _meta.serverTimestamp stamped by EventBus.publish() (with formatSseFrame() fallback for synthetic frames). | 09, 10 |
| Capabilities | SERVE_PROTOCOL_VERSION = 'v1'; 150 registered tags; 44 conditional tags. | 11 |
| Session shell | POST /session/:id/shell exists behind --enable-session-shell, bearer or trusted-loopback authority, and session-bound X-Qwen-Client-Id; capability tag is conditional. | 11, 17, 20 |
| Rate limiting | Optional per-tier HTTP rate limit is exposed by CLI flags/env and conditional capability tag. | 11, 17 |
| Area | Current state | Primary docs |
|---|---|---|
| TypeScript SDK daemon client | DaemonClient, DaemonSessionClient, DaemonAuthFlow, SSE parser, event reducers, feature preflight, and UI transcript exports are documented. | 13 |
| Shared UI transcript layer | SDK daemon/ui/* normalizes daemon events into 42 UI semantic event types, reduces them into transcript blocks, and provides renderers/conformance helpers. | 14, ../daemon-ui/README.md, ../daemon-ui/MIGRATION.md |
| Web UI daemon consumer | packages/webui/src/daemon/ consumes the SDK transcript store through React providers and adapters. | 14, ../daemon-client-adapters/web-ui.md |
| CLI TUI / channels / VS Code | Legacy paths still exist; migration to shared transcript primitives is documented as follow-up work, not completed behavior. | 14, 15, 16 |
| Area | Current state | Primary docs |
|---|---|---|
| Configuration | Full qwen serve flags, env vars, settings.json, ServeOptions, BridgeOptions, and important constants are collected in one page. | 17 |
| Quickstart / operations | Shortest startup path, launch recipes, curl checks, Web Shell auth behavior, route split, shutdown behavior, and embedded invocation recipes are covered. | 20 |
| Errors | Boot-time explicit failures, route errors, bridge errors, EventBus errors, filesystem errors, and mediator errors are summarized with remediation. | 18 |
| Observability | QWEN_SERVE_DEBUG, curl recipes, useful events, telemetry gaps, and investigation checklists are documented. | 19 |
| Surface | Status |
|---|---|
docs/developers/daemon-client-adapters/tui.md | Historical draft for the old DaemonTuiAdapter spike; current shared UI transcript architecture is in doc 14. |
packages/cli/src/ui/daemon/daemon-tui-adapter.ts | Legacy experimental adapter still in-tree. New shared UI work should prefer SDK daemon/ui/*. |
--no-http-bridge | Accepted for compatibility but falls back to http-bridge and prints stderr. |
DAEMON_KNOWN_EVENT_TYPE_VALUES; old SDKs must treat unknown types as forward-compatible.sessionScope: 'thread' is the current per-conversation-thread split; avoid reintroducing older client-scoped wording._meta and ACP payload data._meta are distinct. Tool-call provenance lives under the ACP payload; server emit timestamps live on the SSE envelope.This doc set reflects the daemon mode surface currently merged into main, including the follow-up work from #4412. It intentionally describes current behavior instead of earlier F-series planning snapshots.