13 KiB
Project
ForgeLM
ForgeLM (formerly AI Backend Studio) is a local-first desktop workspace for running and managing local LLM runtimes, selecting models, and chatting against the active runtime from a Tauri app. This roadmap focuses on the existing runtime workspace experience: making runtime control and configuration easier to understand, safer to edit, and more reliable for operators using the desktop app.
Core Value: A user can configure and operate the runtime from one trustworthy workspace without the UI fighting their in-progress edits.
Constraints
- Tech stack: Keep the existing Rust + Tauri + React/TypeScript architecture - the project is improving the current app, not rewriting it
- Brownfield compatibility: Preserve working runtime lifecycle, model selection, and chat flows while reorganizing the UI - regressions in validated capabilities are not acceptable
- UX reliability: Unsaved user edits must not be overwritten by polling or snapshot refresh - trust in the settings surface is the main product constraint
- Local-first: Continue supporting local desktop runtime management patterns already established in the app - scope should not depend on external hosted infrastructure
Technology Stack
Languages
- Rust 2021 - core backend, inference runtime, CLI, shared contracts, metrics, and Tauri desktop backend in
Cargo.toml,crates/inference-server/src/main.rs,crates/inference-core/src/engine.rs,crates/localllm-cli/src/main.rs, andtauri-app/src-tauri/src/lib.rs - TypeScript 5.5 - desktop frontend, runtime manager UI, chat UI, and tests in
tauri-app/package.json,tauri-app/src/App.tsx, andtauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx - CSS - hand-authored styling with app-wide tokens and feature CSS modules in
tauri-app/src/index.css,tauri-app/src/components/Sidebar.css, andtauri-app/src/components/ChatView.css - Markdown - product and architecture docs in
README.MD,docs/api/overview.md, anddocs/app/overview.md - Python - benchmark and experiment scripts in
experiments/bench_chat_latency.py,experiments/bench_cli_surface.py, and related files underexperiments/
Runtime
- Rust toolchain targeting native desktop/server binaries; no workspace-level rust-toolchain file detected
- Node.js runtime for Vite/Tauri frontend workflows in
tauri-app/package.json - Cargo for Rust workspace dependencies and binaries in
Cargo.toml - npm is the documented frontend package manager via
README.MD:47; lockfiles for npm and pnpm are both present intauri-app/package-lock.jsonandtauri-app/pnpm-lock.yaml - Lockfile: present for Rust and frontend in
Cargo.lockandtauri-app/package-lock.json
Frameworks
- Axum 0.8 - local HTTP API in
Cargo.tomlandcrates/inference-server/src/routes.rs - React 18 - desktop UI shell and chat surface in
tauri-app/package.jsonandtauri-app/src/App.tsx - Tauri 2 - desktop shell, local process control, file dialogs, and frontend-to-Rust command bridge in
tauri-app/src-tauri/Cargo.tomlandtauri-app/src-tauri/src/lib.rs - llama.cpp FFI via custom
llama-sys- model loading and token generation incrates/inference-core/src/engine.rsandcrates/inference-core/src/session.rs - Vitest 4 - frontend/unit/component tests in
tauri-app/package.jsonandtauri-app/src/features/runtime/components/RuntimeSurface.test.tsx - Rust built-in test harness - backend/unit tests co-located in files such as
crates/api-contracts/src/chat.rsandtauri-app/src-tauri/src/runtime/state.rs - Vite 5 - frontend dev/build tool in
tauri-app/vite.config.ts - TypeScript compiler - typecheck step in
tauri-app/package.json:9 - Tauri CLI 2 - desktop dev/build entry in
tauri-app/package.json:11
Key Dependencies
tokio- async runtime for API server inCargo.tomlandcrates/inference-server/src/main.rstower-http- CORS and trace middleware inCargo.tomlandcrates/inference-server/src/compat.rsserde/serde_json- shared request/response contracts across API, CLI, and Tauri incrates/api-contracts/src/chat.rsandtauri-app/src-tauri/src/runtime/config.rsclap- CLI command surface incrates/localllm-cli/src/main.rsureq- synchronous HTTP transport for CLI live execution incrates/localllm-cli/src/main.rs:404marked,dompurify,highlight.js- markdown rendering/sanitization/code highlighting intauri-app/src/lib/markdown.ts@tauri-apps/apiand@tauri-apps/plugin-shell- frontend/Tauri bridge intauri-app/package.jsonandtauri-app/src/features/runtime/api.tsuuid- response IDs for chat completions incrates/inference-server/src/routes.rs:126tracingandtracing-subscriber- backend logging and startup diagnostics incrates/inference-server/src/main.rsasync-stream- SSE streaming implementation incrates/inference-server/Cargo.tomlandcrates/inference-server/src/routes.rs:137
Configuration
- Backend runtime is environment-driven via
LOCALLLM_MODEL,LOCALLLM_PROFILE,LOCALLLM_ADDR,LOCALLLM_GPU_LAYERS,LOCALLLM_CTX,LOCALLLM_API_KEY,LOCALLLM_CORS_ORIGINS,LOCALLLM_AUTH_HEADER,LOCALLLM_AUTH_SCHEME,LOCALLLM_SYSTEM_PROMPT, andLOCALLLM_MODEL_ALIASESincrates/inference-server/src/main.rsandcrates/inference-server/src/compat.rs - Desktop runtime config is persisted as JSON in the app data directory through
tauri-app/src-tauri/src/runtime/config.rs - Frontend fallback runtime snapshot is persisted in
localStoragethroughtauri-app/src/features/runtime/api.ts - Rust workspace build in
Cargo.toml - Tauri desktop build in
tauri-app/src-tauri/Cargo.tomlandtauri-app/src-tauri/tauri.conf.json - Frontend dev server/build in
tauri-app/vite.config.tsandtauri-app/package.json
Platform Requirements
- Rust + Cargo for backend and desktop backend in
README.MD:56 - Node.js/npm for the Tauri frontend in
README.MD:57 - Local
.ggufmodel for real inference inREADME.MD:58 - Optional NVIDIA GPU for accelerated local runtime; CPU fallback profile exists in
README.MD:59andcrates/inference-core/src/profile.rs - Local-first desktop deployment via Tauri app in
tauri-app/ - Local HTTP API deployment as standalone binary
localllmincrates/inference-server/Cargo.toml:8
Conventions
Conventions not yet established. Will populate as patterns emerge during development.
Architecture
Pattern Overview
- Keep API contracts in Rust shared types before exposing them to CLI and desktop consumers in
crates/api-contracts/src/lib.rsandcrates/api-contracts/src/chat.rs - Keep inference logic behind a single engine/session boundary in
crates/inference-core/src/engine.rsandcrates/inference-core/src/session.rs - Keep the desktop app as an orchestration shell that manages process lifecycle, model discovery, and chat persistence in
tauri-app/src/App.tsxandtauri-app/src-tauri/src/runtime/mod.rs
Layers
- Purpose: Load GGUF models, own llama context/model pointers, and generate tokens
- Location:
crates/inference-core/src/ - Contains:
EngineConfig,InferenceEngine, runtime profiles, sampler config, generation session - Depends on:
crates/llama-sys, Rust stdlib,anyhow,tracing - Used by:
crates/inference-server/src/main.rs - Purpose: Adapt OpenAI-like chat/model requests to the local engine
- Location:
crates/inference-server/src/ - Contains: env-driven
ServerConfig, auth/CORS rules, prompt preparation, routing, SSE streaming - Depends on:
crates/inference-core,crates/api-contracts,crates/metrics - Used by: local HTTP consumers, CLI, desktop frontend
- Purpose: Keep request/response models and error shapes consistent
- Location:
crates/api-contracts/src/ - Contains: chat completion structs, model list, health payload, error payloads
- Depends on:
serde,serde_json - Used by: server code directly; mirrored conceptually by frontend/CLI callers
- Purpose: Expose operator workflows and a future control plane over HTTP/local actions
- Location:
crates/localllm-cli/src/main.rs - Contains: command parsing, planning, preview rendering, selective live transport
- Depends on:
clap,ureq,serde_json - Used by: developers/operators
- Purpose: Persist runtime config, discover model files, detect GPU, spawn/stop local API
- Location:
tauri-app/src-tauri/src/ - Contains: Tauri commands, runtime state machine, health probing, file dialog integration
- Depends on: Tauri runtime, native process and filesystem APIs
- Used by:
tauri-app/src/features/runtime/api.ts - Purpose: Present runtime controls, model selection, and persistent chat UI
- Location:
tauri-app/src/ - Contains: shell layout, runtime manager hooks, chat view, sidebar, markdown rendering, local DB wrapper
- Depends on: React, fetch, Tauri invoke bridge, browser storage/CDN-loaded sql.js
- Used by: end users of the desktop app
Data Flow
- Backend API state is a single shared
AppStatewithArc<Mutex<InferenceEngine>>incrates/inference-server/src/routes.rs - Desktop runtime state is a single
RuntimeState(pub Mutex<RuntimeInner>)intauri-app/src-tauri/src/runtime/state.rs - Frontend state is local React hook state; no global store is used in
tauri-app/src/App.tsx,tauri-app/src/hooks/useModels.ts, andtauri-app/src/features/runtime/useRuntimeManager.ts - Chat persistence is local-first and browser-backed via
localStorage+ sql.js intauri-app/src/lib/db.ts
Key Abstractions
- Purpose: Own one loaded model and one llama context
- Examples:
crates/inference-core/src/engine.rs,crates/inference-core/src/session.rs - Pattern: Single-owner, RAII-managed native resource wrapper with explicit non-concurrent use
- Purpose: Centralize runtime auth, prompt, CORS, and alias rules
- Examples:
crates/inference-server/src/compat.rs - Pattern: Env-derived compatibility adapter layered in front of the engine
- Purpose: Serialize the desktop runtime state into a frontend-safe shape
- Examples:
tauri-app/src/features/runtime/types.ts,tauri-app/src-tauri/src/runtime/state.rs - Pattern: Backend source of truth mirrored into a polling frontend hook
- Purpose: Hide sql.js statement handling and persistence details behind a tiny query/run API
- Examples:
tauri-app/src/lib/db.ts - Pattern: Thin synchronous local repository over browser storage
Entry Points
- Location:
crates/inference-server/src/main.rs - Triggers:
cargo run -p inference-serveror spawned local desktop runtime - Responsibilities: read env, load/warm engine, build router, bind network listener
- Location:
crates/localllm-cli/src/main.rs - Triggers:
cargo run -p localllm-cli -- ... - Responsibilities: parse commands, build execution plans, optionally perform live HTTP requests
- Location:
tauri-app/src/main.tsxandtauri-app/src/App.tsx - Triggers: Vite dev server or Tauri desktop app startup
- Responsibilities: render app shell, bootstrap DB/runtime hooks, connect sidebar and chat surface
- Location:
tauri-app/src-tauri/src/lib.rs - Triggers: Tauri app startup and frontend
invoke()calls - Responsibilities: expose commands, manage runtime state, wire OS dialogs/plugins
Error Handling
- API uses
ApiError+ErrorResponsewith HTTP status mapping incrates/inference-server/src/routes.rs - Desktop runtime stores recoverable errors in
last_erroronRuntimeSnapshotintauri-app/src-tauri/src/runtime/state.rs - Frontend fetch and invoke failures typically degrade to fallback state or inline assistant error messages in
tauri-app/src/components/ChatView.tsxandtauri-app/src/features/runtime/api.ts
Cross-Cutting Concerns
Boundaries
crates/inference-core/should stay inference-only and not absorb HTTP/UI concernscrates/inference-server/should stay the public backend boundary and not own chat persistence or desktop statecrates/localllm-cli/should stay an operator/client surface and not become the runtime itselftauri-app/src-tauri/should own process/config/filesystem concerns for desktop onlytauri-app/src/should stay a consumer/orchestrator over backend contracts and local chat persistence
GSD Workflow Enforcement
Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.
Use these entry points:
/gsd:quickfor small fixes, doc updates, and ad-hoc tasks/gsd:debugfor investigation and bug fixing/gsd:execute-phasefor planned phase work
Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it.
Developer Profile
Profile not yet configured. Run
/gsd:profile-userto generate your developer profile. This section is managed bygenerate-claude-profile-- do not edit manually.