@octocodeai/freellama-mcp-server 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CONFIGURATION.md +11 -3
  2. package/DEVELOPING.md +6 -6
  3. package/README.md +224 -402
  4. package/dist/index.js +6943 -1602
  5. package/dist/research/bash-agent.js +1495 -71
  6. package/dist/research/coder-agent.js +4668 -0
  7. package/dist/research/github-agent.js +2923 -0
  8. package/dist/research/octocode-agent.js +1407 -116
  9. package/docs/ARCHITECTURE.md +101 -45
  10. package/docs/BUILD_AND_NOTES.md +31 -0
  11. package/docs/CLI.md +76 -27
  12. package/docs/COMPARISON.md +40 -0
  13. package/docs/CPU_GPU_ROUTING.md +127 -25
  14. package/docs/DEFERRED_JOBS.md +79 -0
  15. package/docs/FEATURES.md +303 -0
  16. package/docs/LOCAL_MODELS.md +190 -0
  17. package/docs/MODEL_FORMS_AND_RESULTS.md +55 -0
  18. package/docs/MODEL_INTROSPECTION.md +128 -0
  19. package/docs/MODEL_SELECTION.md +74 -22
  20. package/docs/MONITORING.md +115 -33
  21. package/docs/PRODUCTION.md +74 -11
  22. package/docs/README.md +11 -6
  23. package/docs/SCOPES_AND_WARMING.md +55 -7
  24. package/docs/TESTING.md +24 -2
  25. package/docs/TUNING.md +86 -0
  26. package/docs/cookbooks/README.md +22 -0
  27. package/docs/cookbooks/batch-text.md +19 -0
  28. package/docs/cookbooks/classify.md +25 -0
  29. package/docs/cookbooks/coding.md +17 -0
  30. package/docs/cookbooks/duplicates.md +17 -0
  31. package/docs/cookbooks/find-code.md +21 -0
  32. package/docs/cookbooks/image-recognition.md +15 -0
  33. package/docs/cookbooks/image-search.md +13 -0
  34. package/docs/cookbooks/jobs.md +60 -0
  35. package/docs/cookbooks/memory-and-caching.md +31 -0
  36. package/docs/cookbooks/ocr.md +17 -0
  37. package/docs/cookbooks/research-agent.md +27 -0
  38. package/docs/cookbooks/speech-to-text.md +19 -0
  39. package/docs/cookbooks/sweep.md +66 -0
  40. package/docs/cookbooks/text-to-speech.md +15 -0
  41. package/docs/octocode/GITHUB.md +30 -0
  42. package/docs/octocode/LOCAL.md +29 -0
  43. package/native/index.d.ts +0 -11
  44. package/native/index.js +18 -34
  45. package/package.json +6 -9
package/README.md CHANGED
@@ -1,445 +1,267 @@
1
- # FreeLlama MCP server
1
+ # FreeLlama
2
2
 
3
3
  ![A brown cartoon llama stands on a pastel cloud background.](assets/logo.jpg)
4
4
 
5
- This package exposes FreeLlama's management layer as Model Context Protocol (MCP) tools.
6
- Agents offload bounded tasks to local Ollama models; FreeLlama handles model selection, resource
7
- admission, memory checks, and routing to configured CPU/GPU backends. Results include execution
8
- evidence for the calling agent to inspect.
5
+ **Run your agent's bulk work on local models without overloading your machine.**
9
6
 
10
- The agent owns prompts, task dependencies, and answer verification. The operator configures
11
- Ollama and model lifecycle permissions; Ollama performs inference. See
12
- [architecture](https://github.com/bgauryy/FreeLlama/blob/main/docs/ARCHITECTURE.md) for the full ownership boundary.
13
- The server uses the official [TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk).
7
+ FreeLlama lets coding agents offload bounded work (embeddings, OCR and vision, bulk rewrites,
8
+ classification, summaries) to local [Ollama](https://ollama.com) models instead of spending paid
9
+ tokens and context. For each task it picks an installed model that fits, loads and switches models
10
+ only when they fit in memory, and returns the result with a receipt of where and how it ran. Your
11
+ agent still decides what to offload and verifies the answer.
14
12
 
15
- ## Understand the tools
13
+ ```mermaid
14
+ flowchart LR
15
+ agent["Coding agent<br/>Claude Code, Cursor, any MCP host"]
16
+ cli["freellama CLI"]
17
+ raw["Ollama-compatible client"]
18
+ subgraph fl["FreeLlama, on your machine"]
19
+ mcp["MCP server<br/>Node.js + Rust addon"]
20
+ serve["freellama serve<br/>127.0.0.1:11435"]
21
+ research["Research adapter<br/>read-only, allowlisted files"]
22
+ end
23
+ gpu[("Ollama<br/>GPU: Metal, CUDA, ROCm")]
24
+ cpu[("Optional CPU-only Ollama")]
25
+
26
+ agent -->|"MCP over stdio"| mcp
27
+ mcp -->|"control API"| serve
28
+ cli -->|"control API"| serve
29
+ raw -.->|"/api and /v1 stream through"| serve
30
+ mcp -.->|"delegate_research"| research
31
+ research -->|"each model turn is a managed task"| serve
32
+ serve -->|"route, admit, load, run"| gpu
33
+ serve -.->|"operator-assigned models"| cpu
34
+ ```
35
+
36
+ ## Why FreeLlama
16
37
 
17
- `doctor`, `models`, `run_task`, `task_jobs`, `scope`, and `session` call the Rust core through native NAPI bindings
18
- (`packages/rust-core/src/napi.rs`), with no CLI subprocess and no routing decisions in TypeScript; the
19
- TypeScript layer validates request shapes and derives presentation fields (see
20
- [what the MCP layer computes](#what-the-mcp-layer-computes)). `run_task` has four modes: one task,
21
- `tasks[]` (independent batch), `preview: true` (decision only, no inference), and `warm: true`
22
- (load an exact installed model, no generation). Preview and execution are separate calls: preview
23
- accepts routing fields only and rejects task payloads or runtime controls instead of silently
24
- ignoring them. `ollama_manage` and `ollama_delete` call Ollama's HTTP API directly for lifecycle
25
- operations the routing layer does not perform.
38
+ Coding agents spend paid tokens and context on work a model on your own machine can do: embedding a
39
+ repository, reading screenshots and scans, summarizing or classifying hundreds of files. Pointing
40
+ the agent straight at Ollama does not fix that, because the agent cannot see:
26
41
 
27
- Use the smallest tool that owns the operation; the canonical per-tool table is [Tools](#tools).
42
+ - **Which model fits the job.** A tag name does not show capabilities, context window or memory
43
+ footprint.
44
+ - **Whether there is room.** One more load can push the machine into swap, several agents can pile
45
+ onto one GPU, and a hot or busy machine slows everything.
46
+ - **Whether it worked.** A model can repeat itself until its token cap, and nothing says whether the
47
+ task ran on the GPU or fell back to the CPU.
28
48
 
29
- ## Follow the agent workflow
49
+ FreeLlama answers all three on every call, which makes offloading safe to do by default: the paid
50
+ model keeps the judgment, the local model does the volume, and each answer comes back with a receipt
51
+ you can check. The name means less metered inference, not only Meta's Llama models. More in
52
+ [Features](docs/FEATURES.md#why-freellama).
30
53
 
31
- The task lifecycle uses the UUID returned as `job.id` by `run_task {defer:true}`. A job is one
32
- submitted task; pass that UUID as `jobId` for every subsequent operation.
54
+ ## Requirements
33
55
 
34
- | Operation | MCP call |
56
+ | You need | Why |
35
57
  |---|---|
36
- | List models | `models {view:"installed"}` |
37
- | Submit a task and receive its ID | `run_task {prompt:"Explain this code", defer:true}` |
38
- | List tasks with their states | `task_jobs {action:"list"}` |
39
- | Get one task's state, result, or error | `task_jobs {action:"get", jobId:"<returned UUID>"}` |
40
- | Stop one task and retain its record | `task_jobs {action:"cancel", jobId:"<returned UUID>"}` |
41
- | Stop one task and remove its record | `task_jobs {action:"remove", jobId:"<returned UUID>"}` |
42
-
43
- Removal waits for local permits to be released before deleting the record. It returns the ID and
44
- terminal status; subsequent lookup returns `404`. It does not unload a shared Ollama model or
45
- prove that physical computation has stopped. Receipts are bounded and lost on server restart;
46
- see [retention and task states](https://github.com/bgauryy/FreeLlama/blob/main/docs/MONITORING.md#read-the-live-status).
47
-
48
- Follow this workflow. The server's initialization instructions carry a compressed form of the
49
- same contract (inventory first, preview semantics, evidence levels, ownership, and pull approval):
50
-
51
- 1. Start with `models {view:"installed"}`, then `models {view:"resident"}`. This gives a routing
52
- agent the smallest current inventory first.
53
- 2. Call `doctor` only for runtime or configuration diagnosis. It returns `summary` by default;
54
- use `view:"status"` for live queues and limits or `view:"full"` for the complete diagnostic. If Ollama is missing or unreachable, ask the operator to install or start it.
55
- 3. Classify the task. Offload embeddings, OCR/vision, bulk transforms, and sufficiently large
56
- grounded lookups; retain small lookups and high-stakes judgment in the calling agent.
57
- 4. Prefer a qualified installed model and preview consequential work.
58
- 5. If none fits, collect the operator's modality, quality, context, latency, privacy, disk/download,
59
- and memory constraints. Search the Ollama library, inspect exact tags and host-memory fit, and
60
- present at most two candidates.
61
- 6. Ask the operator to approve one exact tag and its reported size before calling
62
- `ollama_manage {action:"pull"}`. Searching or recommending never authorizes a download.
63
- 7. Execute, inspect the route/execution/admission receipt, and verify the result at the returned
64
- confidence level.
65
-
66
- ### Use context and delegation deliberately
67
-
68
- FreeLlama reduces the **calling agent's context burden**. It does not make an Ollama response more
69
- accurate or eliminate the local model tokens needed to produce it. Its compact text cue avoids a
70
- second serialized copy of the canonical `structuredContent`; its delegated adapter keeps full tool
71
- observations on disk and presents them in pages when requested.
72
-
73
- Use this economical sequence:
74
-
75
- 1. Request `models {view:"installed"}` before `doctor`; inventory is normally the smaller and
76
- more relevant first decision.
77
- 2. Preview consequential generation with `run_task {preview:true}`. Preview is decision-only: it
78
- neither generates nor reserves capacity.
79
- 3. Execute in a separate `run_task` call. Set `contextTokens` for the complete Ollama window and
80
- `options.num_predict` for its output cap. A lower cap or window can lower cost **and** damage a
81
- difficult answer, so choose it from the task rather than a global default.
82
- 4. Use `delegate_research` only for a self-contained question requiring files under
83
- `workspacePath`. Bound `agent.maxTurns`, `agent.contextTokens`, and `agent.outputTokens`.
84
- 5. Keep the compact text cue in the active conversation; inspect `structuredContent`, a paged tool
85
- result, or a bundled documentation resource only when its detail changes the next action.
86
-
87
- For a delegated agent, estimated usable input is `contextTokens - outputTokens - safetyMarginTokens`
88
- (the default margin is 256). The adapter pins the system instruction and question, preserves the
89
- newest observations, compacts older observations into breadcrumbs, and refuses a pinned overflow
90
- by default. `FREELLAMA_AGENT_PINNED_OVERFLOW=clip` is a deliberate quality-risk override. Initial token counting
91
- is conservative; successful Ollama calls calibrate later estimates.
92
-
93
- Do not confuse operational evidence with answer quality. A receipt can prove admission, token
94
- counts, placement, or unloading. It cannot prove research correctness, coding judgment, sustained
95
- throughput, or fairness from one run. Check the returned confidence, policy evidence, and benchmark
96
- evidence before accepting a consequential answer.
97
-
98
- ### Token economics
99
-
100
- Offloading keeps source material and intermediate tool output out of the calling agent's context;
101
- the local model still spends tokens, power, and time. Per-call rows below come from one machine
102
- (M4 Pro, 48 GB unified memory); `~` values are estimates.
103
-
104
- | Work | Source tokens | Returned tokens | Preserved |
105
- |---|---:|---:|---:|
106
- | 6 grounded code questions | 59,208 | 1,742 | **97.1%** |
107
- | 4 text embeddings (307 ms) | 17,600 | ~200 | **98.9%** |
108
- | 1 image, OCR, byte-exact | 1,970 | 37 | **98.1%** |
109
-
110
- A dated MCP-envelope audit (2026-09-03, `characters / 4` as a rough token estimate) measured the
111
- duplicate text copy FreeLlama does not emit beside `structuredContent`: `doctor {view:"summary"}`
112
- avoids ~3,064 chars, `doctor {view:"full"}` ~10,651, `models {view:"raw", limit:1}` ~404. These
113
- are **not billed-token savings** unless the host would otherwise feed both representations to a
114
- model. The tool schema itself is per-turn rent, bounded by the
115
- [protocol context-budget test](https://github.com/bgauryy/FreeLlama/blob/main/packages/mcp/test/integration/protocol.test.ts);
116
- read documentation resources on demand and filter unneeded tools where the client supports it.
117
-
118
- | Cost side | Measured |
58
+ | [Ollama](https://ollama.com/download) running (`ollama list` works) with at least one model | FreeLlama manages Ollama; it does not install, start or replace it, and never downloads a model without your approval |
59
+ | Node.js 22 or newer | Runs the MCP server and the `freellama` npm launcher |
60
+ | One of the platforms below | npm installs the matching prebuilt binary as an optional dependency; do not install with `--omit=optional` |
61
+
62
+ | Platform | Prebuilt package |
119
63
  |---|---|
120
- | Grounded question latency | **7–62 s** vs ~1 s for a frontier model that already holds the file |
121
- | Scaling | turn-dominated: `seconds ≈ 9.8 × tool_calls`, correlation 0.811 over 60 runs |
122
- | Break-even | past ~1k tokens of source the token maths wins; below that, read the file directly |
123
- | Judgment ceiling | ~67% accurate, in the same confident tone as the ~99% case |
124
-
125
- Ollama prefix-cache reuse works on this path (a warm 2,462-token prefix re-prefilled in ~281 ms
126
- versus ~18.6 s cold, and survived an interleaved conversation), so per-turn cost is new-token
127
- prefill plus generation. Context compaction rewrites old observations and invalidates the cache
128
- from that point; leave headroom (for example `OLLAMA_KV_CACHE_TYPE=q8_0`) so compaction stays rare.
129
- Session-scale projections depend on provider, caching, and pricing; measure the client's actual
130
- transcript before claiming a token or billing reduction.
131
-
132
- #### Avoided external cost
133
-
134
- Every successful `run_task`, batch item, and `delegate_research` result includes `telemetry.local`
135
- when Ollama reports input/output token counts. To add `telemetry.externalEquivalent`, configure one
136
- operator-owned rate card when starting the MCP server:
137
-
138
- ```text
139
- FREELLAMA_EXTERNAL_COST_MODEL=EXTERNAL_MODEL_LABEL
140
- FREELLAMA_EXTERNAL_COST_INPUT_USD_PER_M=INPUT_USD_PER_MILLION
141
- FREELLAMA_EXTERNAL_COST_OUTPUT_USD_PER_M=OUTPUT_USD_PER_MILLION
142
- ```
64
+ | macOS, Apple silicon (arm64) | `@octocodeai/freellama-native-darwin-arm64` |
65
+ | Linux x64, glibc | `@octocodeai/freellama-native-linux-x64-gnu` |
66
+ | Linux arm64, glibc | `@octocodeai/freellama-native-linux-arm64-gnu` |
67
+ | Windows x64 | `@octocodeai/freellama-native-win32-x64-msvc` |
68
+ | Windows arm64 | `@octocodeai/freellama-native-win32-arm64-msvc` |
143
69
 
144
- The receipt multiplies observed local input/output counts by those configured rates. It is an
145
- equivalent avoided-API-cost estimate only when the local result replaces an external call. It
146
- excludes provider caching and reasoning-token differences, retries, local electricity, and hardware
147
- amortization; it is not a provider bill or net-profit calculation. Partial or invalid rate-card
148
- configuration stops the MCP server at startup instead of emitting a misleading estimate.
70
+ Intel Macs and musl Linux (such as Alpine) have no prebuilt binary: build from source with Rust 1.89
71
+ or newer ([Build from source](docs/BUILD_AND_NOTES.md#build-from-source)). Optional: a second,
72
+ CPU-only Ollama process for small helper models ([CPU/GPU routing](docs/CPU_GPU_ROUTING.md)).
149
73
 
150
- ### Route images
74
+ ## Install
151
75
 
152
- Use `run_task` for supplied image bytes, not `delegate_research`. Preview
153
- `{task:"vision", requiredCapabilities:["vision"], preview:true}` before a consequential image
154
- task. Execute separately with a prompt and base64 `images` values without data-URI prefixes. The
155
- `images` field needs an explicit trialed vision `model`, or an operator `[policies.vision]` entry in
156
- the serve policy file; without either the core refuses rather than trusting a `vision` capability
157
- tag. Inspect the execution receipt for admission and observed placement.
76
+ ### MCP server (for your agent)
158
77
 
159
- Use the prompt the model documents; dedicated OCR models expect their own task prompts.
160
- FreeLlama adds no stop sequence or other option because of which model was chosen.
78
+ Claude Code:
161
79
 
162
- Some models repeat their answer until the output cap. Set `stopOnRepetition:true` to stream the
163
- task and stop once the output repeats itself; everything generated is kept, and the result
164
- carries `output_check: {stopped_early: true, stop_reason, unique_prefix_chars, ...}`. Without it, a
165
- length-capped answer that ends in a loop gets `output_check: {repetition_loop: true,
166
- unique_prefix_chars, period_chars}`. Either way the MCP answer text shows one copy and the
167
- untrimmed output stays in `structuredContent.response`.
80
+ ```bash
81
+ claude mcp add freellama -- npx -y @octocodeai/freellama-mcp-server
82
+ ```
168
83
 
169
- Routing learns from these loops, not from model names: a model that keeps looping on a task kind
170
- (at least two loops in at most twice as many runs, listed as `observed_loops` by `models`) ranks
171
- last for automatic selection of that task. An explicit `model` or an operator policy still wins.
84
+ Claude Desktop, Cursor and other hosts:
85
+
86
+ ```json
87
+ { "mcpServers": { "freellama": { "command": "npx", "args": ["-y", "@octocodeai/freellama-mcp-server"] } } }
88
+ ```
172
89
 
173
- FreeLlama can prove that it routed and ran a request. It cannot infer OCR or visual-reasoning
174
- quality from a capability tag, a model name, or GPU placement. Quality depends on the exact
175
- installed model build, prompt and decoding settings, context/output budget, and available host
176
- memory and accelerator performance. Validate representative held-out images on the target machine
177
- and supply policy/benchmark evidence before automatically accepting a quality-sensitive result.
90
+ At launch the server starts its own FreeLlama service on `127.0.0.1:11435` if none is running, so
91
+ the CLI is optional. It does not install or start Ollama.
178
92
 
179
- Ownership of decomposition, CPU assignments, placement, and physical execution follows the
180
- [responsibility boundary](https://github.com/bgauryy/FreeLlama/blob/main/docs/ARCHITECTURE.md#responsibility-boundary).
93
+ Required for `delegate_research` in a published install: `FREELLAMA_MCP_ALLOWED_ROOTS` lists the
94
+ directories that tool may read (`:`-separated on macOS and Linux, `;` on Windows). Unset, every local
95
+ `delegate_research` call is refused (its `adapter:"github"` runs without a workspace); the other tools
96
+ do not need it, and `run_task` `files` uses `FREELLAMA_FILE_ROOTS` instead. Add it with
97
+ `claude mcp add freellama -e FREELLAMA_MCP_ALLOWED_ROOTS=/absolute/path/to/your-project -- npx -y @octocodeai/freellama-mcp-server`
98
+ or an `"env": { ... }` entry in JSON. All settings: [MCP configuration](packages/mcp/CONFIGURATION.md).
181
99
 
182
- ## Follow the architecture
100
+ ### CLI (for the terminal)
183
101
 
184
- ```mermaid
185
- flowchart TD
186
- C["MCP client"] -->|"stdio JSON-RPC"| B["dist/index.js: tool registrations"]
187
- B --> N["native/index.js and platform addon"]
188
- N -->|"doctor"| L["Rust diagnostics"]
189
- N -->|"models installed/resident; run_task"| S["freellama serve"]
190
- S --> G["Primary Ollama"]
191
- S --> U["Optional CPU Ollama"]
192
- B -->|"detail, raw; manage; delete"| G
193
- B -->|"library view"| W["ollama.com library + Hugging Face GGUF"]
194
- B -->|"delegate_research"| A["allowlisted local adapter subprocess"]
195
- A --> S
196
- C -->|"resources/read on demand"| D["packaged docs/*.md"]
102
+ ```bash
103
+ npm install -g @octocodeai/freellama
104
+ freellama --version
197
105
  ```
198
106
 
199
- `doctor`, the installed/resident model views, and `run_task` use the NAPI binding instead of a CLI
200
- subprocess. Direct lifecycle and no-serve model views use Ollama HTTP. `delegate_research` starts a
201
- bounded adapter against an allowlisted workspace; each adapter model turn re-enters managed
202
- `run_task` as `coding`, so it shares routing, admission, and placement evidence. The adapters are
203
- TypeScript in `src/research/`, compiled to `dist/research/{bash-agent,octocode-agent}.js`, and run as
204
- `node <file>` in their own process group with the server's Node.js; no Python is required.
205
-
206
- ### What the MCP layer computes
107
+ Without installing, prefix commands with `npx @octocodeai/freellama`. Without Node.js, use
108
+ `cargo install freellama-cli` (Rust 1.89+; the command is still `freellama`).
207
109
 
208
- Model selection, confidence floors, admission, and placement are decided only in the Rust core.
209
- The TypeScript server adds a small set of derived fields on top of core results:
110
+ ## Quick start
210
111
 
211
- - request-shape validation (preview-only fields, embedding versus chat payloads, scope pairs);
212
- - answer text, embedding summaries, and optional avoided-cost telemetry for `run_task`;
213
- - `models {view:"resident"}` placement labels: `gpu_percent` from `resident_vram / resident_size`,
214
- a processor label (core-observed processor first, otherwise derived from that ratio), and
215
- mismatch or partial-offload warnings;
216
- - library-tag `fitsInMemory` against a conservative host-memory budget and a trial candidate;
217
- - the `delegate_research` verification verdict from per-model evidence and tool-call facts.
112
+ ### From your agent
218
113
 
219
- ## Read packaged documentation through MCP
114
+ Ask in plain words; the agent picks the tool ([MCP reference](packages/mcp/README.md)):
220
115
 
221
- The published MCP package includes the Markdown guides from the repository `docs/` directory.
222
- The repository directory remains the source of truth; the package build copies it into `docs/`.
116
+ - "List my local models and tell me which one fits coding tasks."
117
+ - "Use FreeLlama to summarize these 40 files with a local model, then check three summaries."
118
+ - "Read this screenshot with a local OCR model."
223
119
 
224
- MCP clients can list resources and read `freellama://docs/index` (the repository `docs/README.md`),
225
- then fetch exactly one relevant guide such as `freellama://docs/PRODUCTION` or
226
- `freellama://docs/CLI`. Resources are deliberately lazy: do not load every guide into an agent
227
- context. The server fails on startup if the index is absent.
120
+ Or call the tools directly: take the tested pick for the job from the catalog, then run it with
121
+ that `model` (without one, routing picks by capability alone and may choose a model that does
122
+ not fit now).
228
123
 
124
+ ```jsonc
125
+ { "tool": "models", "arguments": { "view": "catalog", "job": "coding" } }
126
+ { "tool": "run_task", "arguments": { "task": "coding", "model": "<catalog pick>", "prompt": "Rename foo to bar in: ...", "options": { "num_predict": 512 } } }
127
+ ```
229
128
 
230
- ## Run
129
+ `run_task {preview:true}` shows the route without running or reserving anything.
231
130
 
232
- **From npm (recommended):**
131
+ ### From the terminal
233
132
 
234
133
  ```bash
235
- npx @octocodeai/freellama-mcp-server
134
+ freellama init # check prerequisites, print a first-run plan; changes nothing
135
+ freellama doctor # Ollama reachability, versions, hardware, effective settings
136
+ freellama catalog # tested model picks per job, what is installed, what fits now
137
+ freellama serve # keep running: the service on http://127.0.0.1:11435
138
+ # in another terminal
139
+ freellama ready # can work be served now, or what is it waiting for
140
+ freellama models
141
+ freellama task --task completion --model MODEL_TAG "Reply with exactly OK."
142
+ freellama status # queues, memory holds, loaded models
236
143
  ```
237
144
 
238
- **From the repository root after building:**
145
+ Replace `MODEL_TAG` with a tag from `models`. `init`, `doctor` and `catalog` work without `serve`.
146
+ Every command has `--help`; the [CLI guide](docs/CLI.md) covers the rest. While `serve` runs, a
147
+ status page is at `http://127.0.0.1:11435/_freellama/ui`.
239
148
 
240
- ```bash
241
- node packages/mcp/dist/index.js
149
+ ## Under the hood
150
+
151
+ Every managed call, from the MCP server, the CLI or the HTTP API, runs through the same Rust core
152
+ and the same gates: route, admit, load, run, observe. Nothing is decided from a model's name.
153
+
154
+ | Owner | Does |
155
+ |---|---|
156
+ | Your agent | Decides what to offload, writes the prompt, verifies the answer |
157
+ | FreeLlama | Picks the model, queues fairly, checks memory and host signals, coordinates loads, writes the receipt |
158
+ | Ollama | Stores models, loads runners, generates tokens |
159
+
160
+ ### Life of one task
161
+
162
+ ```mermaid
163
+ sequenceDiagram
164
+ autonumber
165
+ participant A as Agent
166
+ participant M as MCP server
167
+ participant S as freellama serve
168
+ participant O as Ollama
169
+ A->>M: run_task (task kind, model, prompt)
170
+ M->>S: POST /_freellama/v1/tasks
171
+ Note over S: Route: filter installed models by capability<br/>and context window, rank by policy,<br/>local benchmarks and loop history
172
+ Note over S: Admit: fair queue per backend, weighted 3/2/1<br/>for interactive, normal and background work,<br/>then memory, swap, CPU-load and heat checks
173
+ alt queue full, no room, or wait budget spent
174
+ S-->>M: 429 or 503 with the reason
175
+ else admitted
176
+ opt model not resident
177
+ S->>O: load it under the backend's load lock
178
+ end
179
+ S->>O: chat, generate or embed
180
+ O-->>S: streamed tokens, checked for loops every 16 tokens<br/>when the repetition stop is on
181
+ S->>O: GET /api/ps
182
+ O-->>S: where the runner actually ran, GPU or CPU
183
+ S-->>M: result + receipt
184
+ end
185
+ M-->>A: answer + receipt: route, admission, timing, placement
242
186
  ```
243
187
 
244
- The server speaks MCP over stdio — configure it in your MCP client, do not run it interactively.
245
- At launch it starts `freellama serve` in the background when the default endpoint does not answer;
246
- see `FREELLAMA_MCP_AUTOSTART_SERVE` in [Configuration](CONFIGURATION.md#environment-variables).
188
+ An explicit `model` always wins over routing; FreeLlama never swaps in another model. With
189
+ `defer:true` the same path runs in the background and `task_jobs` returns the receipt.
247
190
 
248
- **Claude Desktop (`claude_desktop_config.json`):**
191
+ ### The memory gate
249
192
 
250
- ```json
251
- {
252
- "mcpServers": {
253
- "freellama": {
254
- "command": "npx",
255
- "args": ["@octocodeai/freellama-mcp-server"]
256
- }
257
- }
258
- }
193
+ A model load has to fit before it starts, so a new load cannot push the machine into swap:
194
+
195
+ ```mermaid
196
+ flowchart TD
197
+ T(["Task admitted"]) --> R{"Model already<br/>resident?"}
198
+ R -->|"yes"| Run(["Run on the resident runner<br/>no new memory"])
199
+ R -->|"no"| P{"OS memory pressure,<br/>or swapping on a large load?"}
200
+ P -->|"yes"| Hold["Hold the load"]
201
+ P -->|"no"| F{"Fits in available memory<br/>and leaves the reserve free?"}
202
+ F -->|"yes"| Load(["Load, then run"])
203
+ F -->|"no"| U["Unload idle runners"]
204
+ U --> F2{"Fits now?"}
205
+ F2 -->|"yes"| Load
206
+ F2 -->|"no"| Hold
207
+ Hold --> W{"Room freed before<br/>the deadline?"}
208
+ W -->|"yes"| P
209
+ W -->|"no"| X(["503 naming the hold<br/>and the largest memory users"])
259
210
  ```
260
211
 
261
- **Cursor / other clients** — use the same `command`/`args` shape in their MCP server config.
262
-
263
- ## Tools
264
-
265
- | Tool | Needs `freellama serve`? | What it does |
266
- |---|---|---|
267
- | `doctor` | No (except `status`/`usage`) | Runtime/configuration diagnostic. Target another Ollama with `ollamaEndpoint` and serve with `serveEndpoint`. `summary` (default) returns endpoint, version, resident count, host/profile signals, and next step; `full` adds all non-duplicated diagnostics, including admission and categorized Ollama settings; `status` returns serve's live view (per-backend queues, current and adaptive limits, circuit breakers, loaded models, host memory, Ollama's effective settings, today's usage); `usage` returns task and token totals per day and model (`days`, default 7). The report distinguishes an observed same-user macOS process from configuration hints and never claims remote process visibility. |
268
- | `models` | `installed` (default) and `resident` do; `detail`/`raw`/`library` don't | Views: `installed` (capabilities, use explanations, derived `model_type`, VRAM, context, policy_rank), `resident` (loaded now + managed GPU/CPU split), `detail` (one model, maximum context), paged `raw` (`GET /api/tags`), `library` (two-step public search: omit `model` to search ollama.com families and, for a `query`, Hugging Face GGUF repos (`source` limits it to one; `limit` applies per source); pass `model:"<family>"` or `model:"hf.co/<owner>/<repo>"` for every pullable tag with its size and `fitsInMemory`). `includeLibrary:true` enriches installed/detail views with sourced public guidance; `includeReadme:true` returns bounded README text in library step 2 or enriched detail. |
269
- | `run_task` | Yes | **Routes or executes** a chat/generate/embed call. `preview: true` accepts routing fields only and returns a decision without generation. Execution omits preview and supplies the payload. Embedding results withhold raw vectors by default (`returnEmbeddings: true` to get them). `tasks: [{id, independent:true, task}]` (max 64, `maxParallelism` bounds fan-out) runs a batch whose nested `task` takes the same fields; it is not a dependency scheduler. `warm: true` warms an exact installed `model` through managed admission with residency/profile controls and optional `defer:true`. |
270
- | `scope` | Yes | Creates, inspects, forks, or deletes process-local message history; history inclusion requires `includeMessages:true`. |
271
- | `session` | Yes | Creates, deletes, or kills model affinity without storing messages or KV; `kill` cancels the session's in-flight work. |
272
- | `task_jobs` | Yes | Inspects, cancels, or removes a deferred task or warming operation. |
273
- | `ollama_manage` | No (direct to Ollama) | `action: "pull"` downloads a model (additive); `action: "stop"` force-unloads it. Both are idempotent |
274
- | `ollama_delete` | No (direct to Ollama) | **Destructive**: permanently removes a model. Call only on an explicit human instruction naming the exact model |
275
- | `delegate_research` | Yes (and spawns the adapter) | Answers a grounded question from files under `workspacePath`; managed coding turns return placement receipts, citations, and an independent verification verdict |
276
-
277
- ### Inspect capabilities and intended uses
278
-
279
- Use `models {view:"installed", includeLibrary:true}` to enrich each installed model, or
280
- `models {view:"detail", model:"gemma3:1b", includeLibrary:true, includeReadme:true}` for one model.
281
- Website access is optional for installed/detail views. Public guidance requires a matching exact tag
282
- and digest prefix; local capabilities remain authoritative and benchmark/policy evidence stays separate.
283
- Family claims have source excerpts and fetch dates, and lookup failures retain local inventory.
284
- Search reports `cloudAvailable` (a cloud variant exists), not whether a family is cloud-only; inspect
285
- exact tags to establish local availability.
286
- See [Model metadata](https://github.com/bgauryy/FreeLlama/blob/main/docs/MODEL_SELECTION.md#model-metadata) for response fields, lookup states, cache bounds,
287
- custom models, and variant limitations.
288
-
289
- ### Preserve Ollama request controls
290
-
291
- The tools declare an MCP object `outputSchema`. Schemas type the stable fields FreeLlama owns
292
- (such as route decision, page, answer, and session identifiers) while leaving Ollama-owned nested
293
- payloads forward-compatible. `structuredContent` is canonical; normal text is a concise cue
294
- (`run_task` and `delegate_research` return the answer text).
295
-
296
- Use `models {view:"raw", limit:20}` and continue with its opaque `page.next_cursor`; a cursor
297
- refuses continuation if the live model list changed. Library tag responses use the same paging
298
- shape. Do not request `doctor {view:"full"}` in an agent loop: use `summary`, `status`, or `usage` for
299
- the smallest diagnostic that answers the question.
300
-
301
- ### Preview and execution
302
-
303
- For ordinary chat, `run_task {prompt:"Hello"}` is enough once the server and an eligible model
304
- are available. `task` defaults to `completion`, including inside batch items. Task profiles are
305
- optional routing presets, not restrictions on what you can ask the model.
306
-
307
- Default `balanced` routing prefers policy-qualified candidates when available. Without an eligible
308
- policy candidate, it falls back to capability/context-compatible models and reports low confidence,
309
- `quality_evidence:"none"`, and `balanced_without_quality_policy`. Set `minConfidence:"medium"`
310
- to require evidence, or `objective:"quality"` to require policy-based selection unless you pin a model.
311
- Memory admission, authentication, and capability requirements apply in every mode.
312
-
313
- `run_task` has two deliberately exclusive request shapes:
314
-
315
- - Preview: set `preview: true`; pass routing fields such as `task`, `objective`, `model`,
316
- `contextTokens`, `requiredCapabilities`, and placement/confidence gates. To preview tool use,
317
- pass `requiredCapabilities: ["tools"]` rather than function definitions.
318
- - Execution: omit `preview` (or set it to `false`) and pass `prompt`, `systemPrompt`, or `messages` for generative
319
- tasks or `input` for embeddings, plus any applicable Ollama runtime controls.
320
-
321
- Preview rejects `prompt`, `systemPrompt`, `messages`, `input`, `images`, `tools`, `keepAlive`, `format`, `think`,
322
- `options`, `logprobs`, `topLogprobs`, `returnEmbeddings`, `priority`, `maxWaitSeconds`, `timeoutSeconds`,
323
- `stopOnRepetition`, `defer`, `scopeId`, and `scopeRevision`. This prevents a client from attaching
324
- work to a decision-only call and mistakenly assuming it ran.
325
-
326
- `run_task.messages` preserves Ollama message fields beyond `role` and `content`, including images,
327
- thinking, tool calls, and tool names. Managed requests also accept `format`, `think`, `options`,
328
- `logprobs`, and `topLogprobs`. Use `contextTokens` for `num_ctx`; placement owns `num_gpu`, so both
329
- keys are rejected inside `options`. The raw proxy remains available when a caller needs an Ollama
330
- endpoint or feature that the managed MCP tool does not expose, including streaming.
331
-
332
- Managed execution waits for a slot and safe host capacity within the server's waiting budget
333
- (120 seconds by default). Set `maxWaitSeconds` on `run_task` or each batch task to request a
334
- shorter budget; the server caps it at its configured limit. Resource waiters remain counted in
335
- the bounded queue after returning their execution slots. They resume when capacity becomes
336
- available, and session cancellation removes pending work. A full queue or an expired deadline
337
- returns a capacity error with retry guidance.
338
-
339
- Set `defer:true` on `run_task` to return a job ID immediately. Use `task_jobs {action:"list"}` for
340
- metadata, `{action:"get", jobId}` for a retained result, and `{action:"cancel", jobId}` to cancel
341
- that task and wait for local permits to be released. `get` summarizes embedding vectors by default;
342
- set `returnEmbeddings:true` to include them. Cancellation does not unload a shared model or confirm
343
- physical runner shutdown. Jobs expire on restart; see [CLI controls](https://github.com/bgauryy/FreeLlama/blob/main/docs/CLI.md#execute-tasks)
344
- for input, result, registry, and retention limits. Batch items cannot defer.
345
-
346
- Set `timeoutSeconds` on a task or batch item for a total deadline covering discovery, queueing,
347
- loading, and inference. The server caps it at its task timeout. The admission wait budget remains
348
- separate; a queue refusal can happen before the total deadline. `priority` selects a fair scheduling
349
- class without bypassing resource checks.
350
-
351
- You own the task instructions. Pass system prompts as `messages` entries with `role:"system"`,
352
- or use `systemPrompt` to prepend one caller-supplied system message. FreeLlama preserves existing
353
- messages and adds no task instructions of its own. A plain `prompt` becomes one user message,
354
- and a supplied `messages` array takes precedence over `prompt`. This also applies to
355
- `task:"code_review"` (an alias for `coding`) and `run_task {tasks}` batches: no review wrapper, mandatory
356
- JSON review format, or review-specific output-token minimum is added.
357
-
358
- The separate `delegate_research` adapter retains internal protocol prompts for its own bounded job. Those prompts are not injected into `run_task`
359
- conversations. Ollama can still apply the selected model's own template or Modelfile defaults.
360
-
361
- `model_type` is a display-oriented value derived from Ollama's additive capabilities:
362
- `generative`, `multimodal`, `embedding_only`, or `unknown`. Routing continues to use the original
363
- capability set, not this summary label. Unknown future Ollama capabilities are omitted from the
364
- typed routing set instead of being treated as a known capability.
365
-
366
- ### Call the control API directly
367
-
368
- Scripts that bypass MCP post the same fields in snake_case to `POST /_freellama/v1/tasks`:
369
- `task`, `objective`, `model`, `session_id`, `required_capabilities`, `prompt` or `messages`,
370
- `images`, `priority`, `keep_alive`, `max_wait_seconds`, `timeout_seconds`, `stop_on_repetition`,
371
- and `request_options: {options, format, think, logprobs, top_logprobs}`. A batch is
372
- `POST /_freellama/v1/task-batches` with `{tasks: [{id, independent: true, task: {...}}], max_parallelism}`; sessions are
373
- `POST /_freellama/v1/sessions` with `{}`. `model` accepts a bare name (`name` resolves to
374
- `name:latest`, or the one installed tag of that family); an ambiguous or unknown name is refused
375
- with the installed candidates. See [Request shapes](https://github.com/bgauryy/FreeLlama/blob/main/docs/ARCHITECTURE.md#request-shapes)
376
- for a full body and the receipt fields.
377
-
378
- ### Retain history and warm models
379
-
380
- Use `scope {action:"create",messages}` to retain a caller-owned prefix. Pass its returned ID and
381
- revision as `scopeId` and `scopeRevision` with only the new input to `run_task`; successful execution
382
- returns the next scope revision. Fork a snapshot before parallel branches. `sessionId` continues to
383
- mean model affinity only.
384
-
385
- Use `run_task {warm:true,model,contextTokens,keepAlive?}` for a matching runner profile. It accepts no task
386
- payload and does not pull a model. Add `defer:true` to inspect its progress through `task_jobs`.
387
- Explicit `keepAlive` wins over finite adaptive retention. See the canonical
388
- [Scope history and model warming reference](https://github.com/bgauryy/FreeLlama/blob/main/docs/SCOPES_AND_WARMING.md) for schemas, limits,
389
- concurrency, privacy, and cache boundaries.
390
-
391
- ### Use CPU assignments through MCP
392
-
393
- `run_task` delegates to `freellama serve`, so it honors the server's `--cpu-upstream` and
394
- `--cpu-model` configuration. Exact assigned models can execute on the CPU process while other
395
- managed tasks execute on the primary GPU-capable process.
396
-
397
- Set `executionPreference` on `run_task` to `auto` (default), `prefer_cpu`, or `prefer_gpu`. This is a
398
- guarded hint: only exact operator-assigned CPU models are eligible, explicit model/session pins win,
399
- and `preview: true` returns `execution.preference_satisfied`, placement, upstream, admission, and a
400
- reason without generating. Automatic feedback normalizes work by tokens and requires three
401
- comparable warm serial samples on both backends with a 10% advantage. It matches model digest,
402
- explicit observed context, effective controls, endpoint-attributed process settings, and managed
403
- admission class. Unknown identity, parallel intervals, and decision-only payload-free previews
404
- use capacity and policy signals. Stored legacy totals do not qualify speed hints. Feedback does
405
- not steer the `quality` objective. See [automatic feedback](https://github.com/bgauryy/FreeLlama/blob/main/docs/CPU_GPU_ROUTING.md#understand-automatic-feedback).
406
- `minPlacementEvidence:"observed"` fails closed unless resident
407
- `/api/ps` evidence matches the configured processor; warm cold models once with `"configured"`.
408
- `keepAlive:"0"` uses an observe-then-unload transaction: FreeLlama retains the runner long enough
409
- to inspect `/api/ps`, accepts feedback only for verified placement, requests an explicit unload,
410
- then reports the unload verification in `execution.lifecycle`.
411
-
412
- Preview `execution.agent_plan` separates `queue_readiness`, `resource_readiness`, and combined
413
- `dispatch_readiness`. Inspect `execution.resource_assessment` for required bytes and missing telemetry;
414
- the preview shares execution's footprint estimate but never reserves memory. Low available RAM alone
415
- never refuses work: previews report `runnable_low_memory_estimate`, and execution dispatches with
416
- `resource_admission.status: "admitted_low_memory_estimate"`. Local inference requires
417
- RAM telemetry by default; configure an explicit alternative on `serve`, not in a model prompt.
418
- Resource errors retain a human-readable `error` plus machine-readable `code` and `resource_admission`
419
- fields in the HTTP response. MCP preserves JSON refusals in both error text and `structuredContent`,
420
- including queue-full codes, `retry_after_seconds`, resource assessments, and unload receipts.
421
- Agents can use those fields to back off or explain a capacity hold without parsing human prose.
422
-
423
- `models {view: "resident"}` uses the managed catalog, so it includes resident models from both
424
- Ollama processes and labels explicitly assigned CPU models instead of querying only the primary
425
- server. The per-model `placement` object is derived in the MCP layer from the catalog's
426
- `resident_size`/`resident_vram` bytes and the core's placement observation; it is a display summary,
427
- not new placement evidence.
428
-
429
- Before relying on that placement, query `/_freellama/v1/health` and require
430
- `contracts.placement_observation:"ollama_api_ps_after_execution"` and
431
- `contracts.placement_evidence_gate:"configured_or_observed"`. A missing contract means the running server
432
- predates the dual-backend build even if the MCP package itself is current.
433
-
434
- The direct Ollama tools do not infer that assignment. `ollama_manage`, `ollama_delete`, and the
435
- no-serve model views target their explicit `ollamaEndpoint` or `FREELLAMA_OLLAMA_ENDPOINT`, which
436
- defaults to the primary Ollama server. Point them at the CPU endpoint only when you intend to
437
- inspect or modify that separate server. Read
438
- [CPU and GPU model routing](https://github.com/bgauryy/FreeLlama/blob/main/docs/CPU_GPU_ROUTING.md) for the complete contract.
439
-
440
- ## More
441
-
442
- - [Configuration](CONFIGURATION.md): environment variables, research-adapter settings, security,
443
- and runtime evidence.
444
- - [Developing](DEVELOPING.md): build, test tiers, platform packages, publishing, and why the server
445
- uses native bindings.
212
+ Resident models keep serving through a hold, except at critical OS memory pressure. Load estimates
213
+ come from model metadata (including the K/V cache at the requested context), and Ollama stays the
214
+ final authority on memory. `--low-memory advisory` admits a tight load with a warning instead of
215
+ waiting. Details: [Architecture](docs/ARCHITECTURE.md#managed-task-execution).
216
+
217
+ ## What to offload
218
+
219
+ Offload bounded work whose result your agent can check; keep judgment in the agent.
220
+
221
+ | Offload | Keep in your agent |
222
+ |---|---|
223
+ | Embeddings, search and deduplication | Small lookups (describing the task costs more than doing it) |
224
+ | OCR and image reading | High-stakes judgment: security review, design, merge decisions |
225
+ | Bulk rewrites, summaries, classification of many files | Edits across files |
226
+ | Questions about workspace files (`delegate_research`) | Final verification of any local answer |
227
+
228
+ Many independent items: `run_task {tasks}`. Long work: `run_task {defer:true}` then `task_jobs`.
229
+ Treat local answers as candidates and spot-check some before relying on the rest.
230
+
231
+ ## Safety
232
+
233
+ - Never pulls a model without approval for one exact tag and size; never deletes one unless you name
234
+ the exact installed tag.
235
+ - Checks each load against live available memory; a load that does not fit waits, then is refused
236
+ with a reason, and resident models keep serving.
237
+ - Unloads only models it warmed or that you name; idle models are unloaded under memory pressure.
238
+ - Holds CPU-bound work on a busy or hot machine and names the signal in the receipt.
239
+ - Binds to loopback; for remote access see [Production](docs/PRODUCTION.md).
240
+
241
+ ## Documentation
242
+
243
+ | Topic | Page |
244
+ |---|---|
245
+ | All guides | [Documentation index](docs/README.md) |
246
+ | CLI commands and flags | [CLI](docs/CLI.md) |
247
+ | MCP tools, schemas, agent workflow | [MCP reference](packages/mcp/README.md), [MCP configuration](packages/mcp/CONFIGURATION.md) |
248
+ | Operating procedure for agents | [FreeLlama skill](skills/freellama/SKILL.md) |
249
+ | Features, routing and admission in depth, why FreeLlama | [Features](docs/FEATURES.md) |
250
+ | How it compares with Ollama, llama.cpp, llama-swap, LocalAI | [Comparison](docs/COMPARISON.md) |
251
+ | Choosing a model | [Model selection](docs/MODEL_SELECTION.md), [local model catalog](docs/LOCAL_MODELS.md) |
252
+ | Model forms, measured results | [Model forms and results](docs/MODEL_FORMS_AND_RESULTS.md) |
253
+ | Recipes per job | [Cookbooks](docs/cookbooks/README.md) |
254
+ | CPU/GPU setup and placement | [CPU/GPU routing](docs/CPU_GPU_ROUTING.md) |
255
+ | Queues, memory, live tuning | [Monitoring](docs/MONITORING.md) |
256
+ | Faster, lighter local models; Ollama settings | [Tuning](docs/TUNING.md) |
257
+ | Background jobs and recovery | [Deferred jobs](docs/DEFERRED_JOBS.md) |
258
+ | History, affinity, warming | [Scopes and warming](docs/SCOPES_AND_WARMING.md) |
259
+ | Deployment and releases | [Production](docs/PRODUCTION.md) |
260
+ | Build from source, operating notes | [Build and notes](docs/BUILD_AND_NOTES.md), [Testing](docs/TESTING.md) |
261
+ | Architecture and ownership | [Architecture](docs/ARCHITECTURE.md) |
262
+ | Embedding the Rust core | [Rust core](packages/rust-core/README.md) |
263
+
264
+ ## License
265
+
266
+ Copyright (c) 2026 Guy Bary. Licensed under [Apache-2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT),
267
+ at your option.