pi-freeflow 1.23.3 → 1.26.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.
package/README.md CHANGED
@@ -1,379 +1,381 @@
1
- # pi-freeflow
2
-
3
- > 31 free models with up to 1M context. No API keys to manage. Add your own relays to spread requests across more IPs.
4
-
5
- Thin by design: a model list, a relay proxy, and a log. The host (`pi-ai`) handles thinking, normalization, and provider behavior.
6
-
7
- [![npm version](https://img.shields.io/npm/v/pi-freeflow?style=flat-square&color=00E5FF)](https://www.npmjs.com/package/pi-freeflow)
8
- [![npm downloads](https://img.shields.io/npm/dm/pi-freeflow?style=flat-square)](https://www.npmjs.com/package/pi-freeflow)
9
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
10
- [![Pi](https://img.shields.io/badge/Powered%20by-Pi-7c3aed?style=flat-square)](https://github.com/badlogic/pi-ai)
11
- [![Oh My Pi](https://img.shields.io/badge/Compatible-OMP-black?style=flat-square)](https://github.com/coder/oh-my-pi)
12
-
13
- ---
14
-
15
- ### What you get
16
-
17
- | Feature | What it does | Cost |
18
- | :--- | :--- | :--- |
19
- | **31 free models** | 8 from OpenCode Zen, 19 from KiloCode Gateway, 4 from Cline, context windows up to 1M. Full list below. | **$0** |
20
- | **Relay pool** | Route requests through your own Cloudflare Workers and Vercel Edge relays. Requests rotate across the pool. A relay that rate-limits, times out, or drops the connection cools down while healthy ones take its traffic. | **$0** beyond your platforms' free tiers |
21
- | **Automatic fallback** | When every relay is cooling down, requests go direct to upstream instead of failing. | **$0** |
22
- | **Short model names** | Every model has a slash-free, colon-free alias, plus an optional `:effort` suffix for thinking depth. You type `freeflow/<name>`. | **$0** |
23
- | **Shared local proxy** | One daemon on `127.0.0.1:28180` serves every session on the machine, so parallel subagents reuse it instead of opening their own connections. | **$0** |
24
- | **Logs you can read** | `~/.pi/agent/pi-freeflow.log`, rotated at 10MB. Tail it with `/freeflow logs`. | **$0** |
25
-
26
- ---
27
-
28
- ### Install
29
-
30
- **On Oh My Pi (OMP):**
31
- ```bash
32
- omp plugin install pi-freeflow
33
- # or local dev (repo checkout)
34
- omp plugin link /path/to/pi-freeflow
35
- ```
36
-
37
- **On Pi:**
38
- ```bash
39
- pi install npm:pi-freeflow
40
- ```
41
-
42
- > Both commands fetch the same npm package from the registry. pi-freeflow
43
- > is an extension loaded by the host, not a standalone CLI. It works on OMP
44
- > and Pi only (they share the extension API).
45
-
46
- ### Pick a model
47
-
48
- **OMP, interactive:**
49
- ```bash
50
- omp
51
- /model → freeflow → muse-spark-1.2-contributor-free (1M) → max
52
- ```
53
-
54
- **OMP, one shot:**
55
- ```bash
56
- omp -p --model freeflow/muse-spark-1.2-contributor-free "build me a SaaS"
57
- omp -p --model freeflow/step-3.7-flash:high "solve this bug" # alias + thinking level
58
- ```
59
-
60
- **Pi, interactive:**
61
- ```bash
62
- pi
63
- /model → freeflow → pick
64
- ```
65
-
66
- **Pi, one shot:**
67
- ```bash
68
- pi -p --model freeflow/step-3.7-flash:high "solve this bug"
69
- ```
70
-
71
- Model IDs accept a full canonical ID, a short alias (see the tables below),
72
- and an optional `:effort` suffix (`:minimal` through `:xhigh`, `:max` where
73
- supported). The host resolves the rest.
74
-
75
- ### Add relays
76
-
77
- The default setup talks to upstream directly. Add relays when shared IPs start
78
- hitting rate limits. The fastest path is guided deploy: run
79
- `/freeflow deploy cloudflare` (or `deno`, `vercel`), paste your platform token
80
- once when asked, and the relay is created and added to your pool. The token
81
- stays in memory and is never written to disk.
82
-
83
- Manual fallback per platform:
84
-
85
- **Option A: Cloudflare Workers, auto deploy**
86
- ```bash
87
- /freeflow deploy cloudflare # prompts token in-memory, auto-adds to pool
88
- ```
89
- Manual fallback: `dash.cloudflare.com` → Workers → Create → Deploy → Edit code → paste the canonical worker source (see below) → Deploy → `/freeflow add https://your.workers.dev cf-worker-1`
90
-
91
- **Option B: Vercel Edge Relay, auto deploy**
92
- ```bash
93
- /freeflow deploy vercel # prompts token in-memory, auto-adds to pool
94
- # or shorthand: /freeflow deploy
95
- ```
96
- Manual fallback: push 2 files (`api/relay.js` + `vercel.json`) to GitHub, then Import on `vercel.com`, then `/freeflow add https://your.vercel.app vercel-relay-1`
97
-
98
- For `api/relay.js`, use the canonical worker source (see below); `vercel.json` stays:
99
-
100
- ```json
101
- { "rewrites": [{ "source": "/(.*)", "destination": "/api/relay" }] }
102
- ```
103
-
104
- **Option C: Deno Deploy, auto deploy**
105
- ```bash
106
- /freeflow deploy deno # prompts token in-memory, auto-adds to pool
107
- ```
108
- Manual fallback: `dash.deno.com` → New Project → Playground → paste the canonical worker source (see below) → Deploy → `/freeflow add https://your-project.deno.dev deno-relay-1`
109
-
110
- **Canonical worker source (all platforms)**
111
-
112
- The relay worker template is generated per deployment by `/freeflow deploy`, with one shared core adapted for Vercel, Cloudflare, and Deno. Deployed relays accept requests from any pi-freeflow user by default, while only forwarding to an allowlist (`https://opencode.ai`, `https://api.kilo.ai`) with private-host and path checks.
113
-
114
- ```js
115
- // Minimal Cloudflare illustration. Prefer /freeflow deploy: the generated
116
- // worker is the hardened source for all three platforms.
117
- // This example omits the private-host guard, path validation, and auth.
118
- const ALLOWED_TARGETS = ["https://opencode.ai", "https://api.kilo.ai"];
119
- export default {
120
- async fetch(req) {
121
- const target = req.headers.get("x-relay-target");
122
- const relayPath = req.headers.get("x-relay-path") || "/";
123
- if (!target || !ALLOWED_TARGETS.includes(target.replace(/\/$/, ""))) {
124
- return new Response(JSON.stringify({ error: "Forbidden target" }), { status: 403 });
125
- }
126
- const headers = new Headers(req.headers);
127
- headers.delete("x-relay-target"); headers.delete("x-relay-path"); headers.delete("host");
128
- return fetch(target.replace(/\/$/, "") + relayPath, { method: req.method, headers, body: req.method !== "GET" && req.method !== "HEAD" ? req.body : undefined });
129
- },
130
- };
131
- ```
132
-
133
- **Verify your pool:**
134
- ```bash
135
- /freeflow status # active relay, pool status, candidates
136
- /freeflow list # every relay with health status
137
- /freeflow logs # tail -25
138
- ```
139
-
140
- ### Carry your pool to another machine
141
-
142
- ```bash
143
- /freeflow export # save pool to ./freeflow-relays.json
144
- /freeflow export backup/team.json # save to a path you choose
145
- /freeflow import backup/team.json # add its relays to this machine (merge)
146
- /freeflow import backup/team.json --replace --dry-run # preview a full swap first
147
- ```
148
-
149
- Merge is the default and never deletes anything. Replace swaps the whole pool
150
- and always asks first. Passwords stay out of the file unless you pass
151
- `--include-secrets`; a file without passwords still imports, and you re-enter
152
- each password once afterwards.
153
-
154
- ---
155
-
156
- ### Commands reference (`/freeflow`)
157
-
158
- The same command set works identically in OMP and Pi:
159
-
160
- ```bash
161
- /freeflow status # View active relay, pool status, and candidates
162
- /freeflow list # List all relays with real-time health badges
163
- /freeflow use <url|index|label> # Switch active relay
164
- /freeflow url <url> # Set the active relay URL directly
165
- /freeflow add <url> [label] # Add new relay to the pool
166
- /freeflow label <index|url> <name># Assign a friendly label to a relay
167
- /freeflow remove <index|url|label># Remove a relay from the pool
168
- /freeflow test <index|url|label> # Probe a relay for reachability and latency
169
- /freeflow on | off | auto # Toggle relay mode (auto = enabled for freeflow)
170
- /freeflow deploy <platform> # Guided relay deploy: vercel|cloudflare|deno, token in-memory, auto-adds
171
- /freeflow logs [lines] # Inspect recent proxy logs
172
- /freeflow trace [req-id] # Tail logs filtered by request correlation ID
173
- /freeflow refresh # Reload the model catalog from live upstreams
174
- /freeflow update # Check for and install a package update
175
- /freeflow debug on | off # Toggle full HTTP lifecycle debug logging
176
- /freeflow kill # Stop the shared proxy daemon now (restarts on next use)
177
- /freeflow cline login # Sign in through the browser, save to the per-user pool
178
- /freeflow cline accounts # List saved Cline logins
179
- /freeflow cline logout # Remove a saved Cline login
180
- /freeflow cline signout # Link to sign out of Cline in your browser (to add another account)
181
- /freeflow export [path] [--include-secrets] # Save the relay pool to a file (default freeflow-relays.json; passwords left out unless asked)
182
- /freeflow import <path> [--merge|--replace] [--dry-run] # Load a relay pool from a file (merge is default; replace asks first; dry-run previews only)
183
- ```
184
-
185
- ---
186
-
187
- ### 31 models, one command
188
-
189
- ```bash
190
- /model → freeflow → pick
191
- ```
192
-
193
- #### OpenCode Zen (8 models), Responses, Chat, and Messages API
194
-
195
- Good defaults for long coding sessions and agentic work.
196
-
197
- | Model ID | Creator / Lab | Context | Max Output | Thinking | Vision |
198
- | :--- | :--- | :--- | :--- | :--- | :--- |
199
- | `muse-spark-1.2-contributor-free` | Meta Superintelligence Labs | **1M** (1.048.576) | **131K** (131.072) | `minimal … xhigh` | ✅ |
200
- | `muse-spark-1.3-contributor-free` | Meta Superintelligence Labs | **1M** (1.048.576) | **131K** (131.072) | `minimal … xhigh` | ✅ |
201
- | `mimo-v2.5-free` | Xiaomi MiMo | **1M** (1.048.576) | **131K** (131.072) | `minimal … xhigh`\* | ✅ |
202
- | `nemotron-3.5-lightning-free` | NVIDIA | **1M** (1.000.000) | **262K** (262.144) | `minimal … xhigh` | ❌ |
203
- | `nemotron-3-ultra-free` | NVIDIA | **1M** (1.000.000) | **128K** (128.000) | `minimal … xhigh` | ❌ |
204
- | `big-pickle` | Big Pickle | **200K** (200.000) | **32K** (32.000) | `high / max` | ❌ |
205
- | `ling-3.0-flash-fin-free` | Inclusion AI | **262K** (262.144) | **131K** (131.072) | `minimal … xhigh` | ❌ |
206
- | `union-alpha` | Union | **262K** (262.144) | **131K** (131.072) | — *(no effort levels)* | ✅ |
207
-
208
- #### KiloCode Gateway (19 models), OpenRouter compatible
209
-
210
- Keyless access. Short aliases work for every row (the full ID is in parentheses).
211
-
212
- | Model ID | Creator / Lab | Context | Max Output | Thinking | Vision |
213
- | :--- | :--- | :--- | :--- | :--- | :--- |
214
- | `dots-3-note-preview` (`dots-studio/...:free`) | Dots Studio | **512K** (512.000) | **512K** (512.000) | `minimal…xhigh`\* | ✅ |
215
- | `step-3.7-flash` (`stepfun/...:free`) | StepFun | **262K** (262.144) | **262K** (262.144) | `minimal…xhigh`\* | ✅ |
216
- | `nemotron-3-nano-omni` (`nvidia/...:free`) | NVIDIA | **256K** (256.000) | **131K** (131.072) | `minimal…xhigh`\* | ✅ |
217
- | `nemotron-3-ultra-550b` (`nvidia/...:free`) | NVIDIA | **1M** (1.000.000) | **128K** (128.000) | `minimal…xhigh`\* | ❌ |
218
- | `nvidia/nemotron-3.5-lightning:free` | NVIDIA | **1M** (1.000.000) | **262K** (262.144) | `minimal…xhigh`\* | ❌ |
219
- | `nemotron-3-super` (`nvidia/...:free`) | NVIDIA | **262K** (262.144) | **262K** (262.144) | `minimal…xhigh`\* | ❌ |
220
- | `north-mini-code` (`cohere/...:free`) | Cohere | **256K** (256.000) | **64K** (64.000) | `minimal…xhigh`\* | ❌ |
221
- | `laguna-s-2.1:free` (`poolside/...:free`) | Poolside | **262K** (262.144) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
222
- | `laguna-xs-2.1:free` (`poolside/...:free`) | Poolside | **262K** (262.144) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
223
- | `lfm-2.5` (`liquid/lfm-2.5-2.6b:free`) | Liquid AI | **65K** (65.536) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
224
- | `kilo-auto` (`kilo-auto/free`) | Kilo Gateway Auto | **256K** (256.000) | **10K** (10.000) | `minimal…xhigh`\* | ❌ |
225
- | `openrouter` (`openrouter/free`) | OpenRouter Free | **200K** (200.000) | **65K** (65.536) | `minimal…xhigh`\* | ✅ |
226
- | `content-safety` (`nvidia/...:free`) | NVIDIA | **128K** (128.000) | **8K** (8.192) | ❌ *(non-thinking)* | ✅ |
227
- | `ling-3.0-flash-fin` (`inclusionai/ling-3.0-flash-fin:free`) | Inclusion AI | **262K** (262.144) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
228
- | `ling-3.0-flash-sante` (`inclusionai/ling-3.0-flash-sante:free`) | Inclusion AI | **262K** (262.144) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
229
- | `nex-n2.5-pro` (`nex-agi/nex-n2.5-pro:free`) | Nex AGI | **262K** (262.144) | **235K** (235.929) | `minimal…xhigh`\* | ✅ |
230
- | `nex-n2.5-mini` (`nex-agi/nex-n2.5-mini:free`) | Nex AGI | **262K** (262.144) | **235K** (235.929) | `minimal…xhigh`\* | ✅ |
231
- | `ling-3.0-flash-vl` (`inclusionai/ling-3.0-flash-vl:free`) | Inclusion AI | **262K** (262.144) | **32K** (32.768) | `minimal…xhigh`\* | ✅ |
232
- | `inkling-small` (`thinkingmachines/inkling-small:free`) | Thinking Machines | **1M** (1.048.576) | **262K** (262.144) | `minimal…xhigh`\* | ✅ |
233
-
234
- \* Levels are forwarded as-is through the OpenRouter-style nested `reasoning` parameter; effort mapping is decided by each model. MiMo collapses `minimal→low` and `xhigh→high` upstream, so its selector shows 5 labels but only 3 distinct effort values.
235
-
236
- #### Cline (4 models), OpenAI compatible
237
-
238
- Rotating per-account promo, direct only (never through the relay pool). Sign in through your browser with `/freeflow cline login`, manage with `/freeflow cline accounts` and `/freeflow cline logout`. Requests roll across saved logins when one hits its daily free limit.
239
-
240
- Add as many logins as you want — each one gets its own slot (`default`, `slot-2`, `slot-3`, …) and a request that hits a limit on one rolls straight to the next. To sign in with a different email, sign out of Cline in that browser first (`/freeflow cline signout` prints the link), or use a private window so your current session stays put.
241
-
242
- Each account can only be saved once: an extra login for an account you already have shares the same free quota, so it is refused rather than saved. If a pool already holds two logins for one account (saved before this check), `/freeflow cline accounts` marks the later one `— same account as [default]`, and `/freeflow cline logout <slot>` drops it.
243
-
244
- | Model ID | Creator / Lab | Context | Max Output | Thinking | Vision |
245
- | :--- | :--- | :--- | :--- | :--- | :--- |
246
- | `cline-free/deepseek-v4.1-flash` | DeepSeek | **1M** (1.000.000) | **384K** (384.000) | `low/high/max` | ✅ |
247
- | `cline-free/muse-spark-1.3-contributor` | Meta Superintelligence Labs | **1M** (1.048.576) | **131K** (131.072) | `minimal…xhigh`\* | ✅ |
248
- | `z-ai/glm-5.3-flash` | Zhipu AI | **1M** (1.000.000) | **131K** (131.072) | `low/high/max` | ✅ |
249
- | `cline-free/solar-pro4` | Upstage | **512K** (524.288) | **131K** (131.072) | `minimal…max`\* | ❌ |
250
-
251
- ---
252
-
253
- ### Logs and debugging
254
-
255
- ```bash
256
- /freeflow logs
257
- cat ~/.pi/agent/pi-freeflow.log | tail -n 50
258
-
259
- # full debug logging is on by default; `off` restores info level
260
- /freeflow debug on
261
- ```
262
-
263
- ---
264
-
265
- ### Design
266
-
267
- This package stays thin. It ships three things: a model catalog, a relay proxy, and a log. There is no build step and zero runtime dependencies. Thinking and prompt normalization stay with the host (`pi-ai`).
268
-
269
- About 19k lines including tests. The full suite (sandboxed, network-mocked) and typecheck pass before every release. See CHANGELOG.md.
270
-
271
- ---
272
-
273
- ### FAQ
274
-
275
- **Do I need API keys?**
276
- No. Kilo uses a shared free credential and OpenCode free models need no header. You never paste a key. Cline free models need a browser login instead: `/freeflow cline login` saves it to a per-user pool on your machine.
277
-
278
- **What if all relays hit rate limits?**
279
- The proxy tries direct upstream. If that is also rate-limited, the host shows the limit. That number is the shared upstream cap; without relays you would hit the same wall sooner.
280
-
281
- **Can I use it without relays?**
282
- Yes. `/freeflow off` talks direct. Add relays later when you need them.
283
-
284
- **What happens when I update to a new version?**
285
- The local proxy daemon is shared across sessions on port 28180. On upgrade, the new extension
286
- detects a stale daemon (an older version still running) and replaces it automatically, with no manual
287
- kill and no restart of other sessions. Replacement only happens when the running daemon is
288
- idle: sessions with in-flight requests are never interrupted (busy or newer daemons are reused
289
- with a log note instead). If a daemon cannot be replaced (for example the port is held by an unrelated process),
290
- it falls back to reusing it with a warning. To disable replacement entirely, set the no-kill env
291
- to `1` before starting a session.
292
-
293
- **What happens when I close a session?**
294
- Nothing visible to your other sessions. The proxy daemon is a separate background
295
- process shared by every OMP/Pi session on the machine. Closing one session just
296
- unregisters it; the daemon keeps serving the rest and retires itself automatically
297
- once the last client disconnects and no client re-attaches within a short grace window.
298
- To stop it manually, run `/freeflow kill`. The next freeflow use starts it again.
299
-
300
- **Why did my long session stop with a "reasoning was not issued to this caller" error?**
301
- The upstream backend signs each thinking block so only the backend that produced it can read it back. When a later turn reaches a different backend, the old blocks get rejected and the session stalls. pi-freeflow keeps each conversation on the relay that produced its thinking while that relay is healthy. When the relay has to change anyway (rate limit, relay removed, direct-mode switch), that turn is sent without the old thinking blocks so the new backend accepts it, and only the rejected blocks are dropped afterwards. Messages, tool calls, and tool results are always kept.
302
-
303
- **Why is it installed via npm?**
304
- The npm package is the distribution channel only. Both hosts resolve it internally:
305
- `omp plugin install pi-freeflow` and `pi install npm:pi-freeflow` install the same
306
- package from the npm registry. pi-freeflow is an extension, not a standalone CLI.
307
- The host (OMP or Pi) loads and runs it. A plain `npm install` just downloads the
308
- files; it is not a supported way to run the extension.
309
-
310
- **Which hosts can use it?**
311
- Oh My Pi (OMP) and Pi only. They share the same extension API, so one
312
- package serves both. Other AI agents (OpenCode, KiloCode, Cursor, and similar) have their
313
- own plugin systems and do not load this extension.
314
-
315
- ---
316
-
317
- ### Contributing
318
-
319
- Contributions welcome: bug fixes, new relay platforms, model additions, docs improvements.
320
-
321
- #### Prerequisites
322
-
323
- - **Node.js ≥ 22.19.0** (uses `--experimental-strip-types`, no build step)
324
- - **pnpm** (package manager)
325
-
326
- #### Setup and verify
327
-
328
- ```bash
329
- git clone https://github.com/trefeon/pi-freeflow
330
- cd pi-freeflow
331
- pnpm install
332
-
333
- # run all three before opening a PR
334
- pnpm test # full suite; sandboxed and network-mocked
335
- pnpm typecheck # tsc --noEmit, must pass clean
336
- pnpm smoke # verifies extensions/index.ts loads without crashing
337
- ```
338
-
339
- #### Project structure
340
-
341
- ```
342
- src/
343
- ├── index.ts # extension entry, lifecycle hooks
344
- ├── models.ts # 31-model catalog definitions
345
- ├── catalog.ts # model catalog cache (24h disk)
346
- ├── proxy.ts # local proxy server (127.0.0.1:28180)
347
- ├── relay.ts # relay selection and round-robin
348
- ├── relay-state.ts # relay pool state, health tracking
349
- ├── stream-pipe.ts # SSE stream piping and truncation resilience
350
- ├── commands.ts # /freeflow CLI subcommands
351
- ├── deploy.ts # guided relay deploy (vercel/cloudflare/deno)
352
- ├── config.ts # constants, whitelists, paths, and runtime settings
353
- ├── logger.ts # file logger with 10MB rotation
354
- └── types.ts # shared type definitions
355
- extensions/
356
- └── index.ts # OMP/Pi extension manifest
357
- test/
358
- └── *.test.ts # mirrors src/, node:test runner
359
- ```
360
-
361
- #### Guidelines
362
-
363
- - **Stay thin.** Zero runtime dependencies, no build step. If it belongs in the host (`pi-ai`), don't add it here.
364
- - **Test what you touch.** Every `src/*.ts` has a matching `test/*.test.ts`. Add or update tests for your change.
365
- - **Keep model IDs clean.** Slash-free, colon-free aliases for CLI compatibility. See existing patterns in `models.ts`.
366
- - **One concern per PR.** Bug fix? One PR. New relay platform? Separate PR. Easier to review, faster to merge.
367
-
368
- #### Reporting issues
369
-
370
- Found a bug or want a feature? [Open an issue](https://github.com/trefeon/pi-freeflow/issues) with:
371
- - What happened vs what you expected
372
- - Your relay setup (`/freeflow status` output helps)
373
- - Relevant logs (`/freeflow logs` or `~/.pi/agent/pi-freeflow.log`)
374
-
375
- ---
376
-
377
- ### License
378
-
379
- MIT © trefeon
1
+ # pi-freeflow
2
+
3
+ > 33 free models with up to 1M context. No API keys to manage. Add your own relays to spread requests across more IPs.
4
+
5
+ Thin by design: a model list, a relay proxy, and a log. The host (`pi-ai`) handles thinking, normalization, and provider behavior.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/pi-freeflow?style=flat-square&color=00E5FF)](https://www.npmjs.com/package/pi-freeflow)
8
+ [![npm downloads](https://img.shields.io/npm/dm/pi-freeflow?style=flat-square)](https://www.npmjs.com/package/pi-freeflow)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
10
+ [![Pi](https://img.shields.io/badge/Powered%20by-Pi-7c3aed?style=flat-square)](https://github.com/badlogic/pi-ai)
11
+ [![Oh My Pi](https://img.shields.io/badge/Compatible-OMP-black?style=flat-square)](https://github.com/coder/oh-my-pi)
12
+
13
+ ---
14
+
15
+ ### What you get
16
+
17
+ | Feature | What it does | Cost |
18
+ | :--- | :--- | :--- |
19
+ | **33 free models** | 9 from OpenCode Zen, 19 from KiloCode Gateway, 5 from Cline, context windows up to 1M. Full list below. | **$0** |
20
+ | **Relay pool** | Route requests through your own Cloudflare Workers and Vercel Edge relays. Requests rotate across the pool. A relay that rate-limits, times out, or drops the connection cools down while healthy ones take its traffic. | **$0** beyond your platforms' free tiers |
21
+ | **Automatic fallback** | When every relay is cooling down, requests go direct to upstream instead of failing. | **$0** |
22
+ | **Short model names** | Every model has a slash-free, colon-free alias, plus an optional `:effort` suffix for thinking depth. You type `freeflow/<name>`. | **$0** |
23
+ | **Shared local proxy** | One daemon on `127.0.0.1:28180` serves every session on the machine, so parallel subagents reuse it instead of opening their own connections. | **$0** |
24
+ | **Logs you can read** | `~/.pi/agent/pi-freeflow.log`, rotated at 10MB. Tail it with `/freeflow logs`. | **$0** |
25
+
26
+ ---
27
+
28
+ ### Install
29
+
30
+ **On Oh My Pi (OMP):**
31
+ ```bash
32
+ omp plugin install pi-freeflow
33
+ # or local dev (repo checkout)
34
+ omp plugin link /path/to/pi-freeflow
35
+ ```
36
+
37
+ **On Pi:**
38
+ ```bash
39
+ pi install npm:pi-freeflow
40
+ ```
41
+
42
+ > Both commands fetch the same npm package from the registry. pi-freeflow
43
+ > is an extension loaded by the host, not a standalone CLI. It works on OMP
44
+ > and Pi only (they share the extension API).
45
+
46
+ ### Pick a model
47
+
48
+ **OMP, interactive:**
49
+ ```bash
50
+ omp
51
+ /model → freeflow → muse-spark-1.2-contributor-free (1M) → max
52
+ ```
53
+
54
+ **OMP, one shot:**
55
+ ```bash
56
+ omp -p --model freeflow/muse-spark-1.2-contributor-free "build me a SaaS"
57
+ omp -p --model freeflow/space-bunny:high "solve this bug" # alias + thinking level
58
+ ```
59
+
60
+ **Pi, interactive:**
61
+ ```bash
62
+ pi
63
+ /model → freeflow → pick
64
+ ```
65
+
66
+ **Pi, one shot:**
67
+ ```bash
68
+ pi -p --model freeflow/space-bunny:high "solve this bug"
69
+ ```
70
+
71
+ Model IDs accept a full canonical ID, a short alias (see the tables below),
72
+ and an optional `:effort` suffix (`:minimal` through `:xhigh`, `:max` where
73
+ supported). The host resolves the rest.
74
+
75
+ ### Add relays
76
+
77
+ The default setup talks to upstream directly. Add relays when shared IPs start
78
+ hitting rate limits. The fastest path is guided deploy: run
79
+ `/freeflow deploy cloudflare` (or `deno`, `vercel`), paste your platform token
80
+ once when asked, and the relay is created and added to your pool. The token
81
+ stays in memory and is never written to disk.
82
+
83
+ Manual fallback per platform:
84
+
85
+ **Option A: Cloudflare Workers, auto deploy**
86
+ ```bash
87
+ /freeflow deploy cloudflare # prompts token in-memory, auto-adds to pool
88
+ ```
89
+ Manual fallback: `dash.cloudflare.com` → Workers → Create → Deploy → Edit code → paste the canonical worker source (see below) → Deploy → `/freeflow add https://your.workers.dev cf-worker-1`
90
+
91
+ **Option B: Vercel Edge Relay, auto deploy**
92
+ ```bash
93
+ /freeflow deploy vercel # prompts token in-memory, auto-adds to pool
94
+ # or shorthand: /freeflow deploy
95
+ ```
96
+ Manual fallback: push 2 files (`api/relay.js` + `vercel.json`) to GitHub, then Import on `vercel.com`, then `/freeflow add https://your.vercel.app vercel-relay-1`
97
+
98
+ For `api/relay.js`, use the canonical worker source (see below); `vercel.json` stays:
99
+
100
+ ```json
101
+ { "rewrites": [{ "source": "/(.*)", "destination": "/api/relay" }] }
102
+ ```
103
+
104
+ **Option C: Deno Deploy, auto deploy**
105
+ ```bash
106
+ /freeflow deploy deno # prompts token in-memory, auto-adds to pool
107
+ ```
108
+ Manual fallback: `dash.deno.com` → New Project → Playground → paste the canonical worker source (see below) → Deploy → `/freeflow add https://your-project.deno.dev deno-relay-1`
109
+
110
+ **Canonical worker source (all platforms)**
111
+
112
+ The relay worker template is generated per deployment by `/freeflow deploy`, with one shared core adapted for Vercel, Cloudflare, and Deno. Deployed relays accept requests from any pi-freeflow user by default, while only forwarding to an allowlist (`https://opencode.ai`, `https://api.kilo.ai`) with private-host and path checks.
113
+
114
+ ```js
115
+ // Minimal Cloudflare illustration. Prefer /freeflow deploy: the generated
116
+ // worker is the hardened source for all three platforms.
117
+ // This example omits the private-host guard, path validation, and auth.
118
+ const ALLOWED_TARGETS = ["https://opencode.ai", "https://api.kilo.ai"];
119
+ export default {
120
+ async fetch(req) {
121
+ const target = req.headers.get("x-relay-target");
122
+ const relayPath = req.headers.get("x-relay-path") || "/";
123
+ if (!target || !ALLOWED_TARGETS.includes(target.replace(/\/$/, ""))) {
124
+ return new Response(JSON.stringify({ error: "Forbidden target" }), { status: 403 });
125
+ }
126
+ const headers = new Headers(req.headers);
127
+ headers.delete("x-relay-target"); headers.delete("x-relay-path"); headers.delete("host");
128
+ return fetch(target.replace(/\/$/, "") + relayPath, { method: req.method, headers, body: req.method !== "GET" && req.method !== "HEAD" ? req.body : undefined });
129
+ },
130
+ };
131
+ ```
132
+
133
+ **Verify your pool:**
134
+ ```bash
135
+ /freeflow status # active relay, pool status, candidates
136
+ /freeflow list # every relay with health status
137
+ /freeflow logs # tail -25
138
+ ```
139
+
140
+ ### Carry your pool to another machine
141
+
142
+ ```bash
143
+ /freeflow export # save pool to ./freeflow-relays.json
144
+ /freeflow export backup/team.json # save to a path you choose
145
+ /freeflow import backup/team.json # add its relays to this machine (merge)
146
+ /freeflow import backup/team.json --replace --dry-run # preview a full swap first
147
+ ```
148
+
149
+ Merge is the default and never deletes anything. Replace swaps the whole pool
150
+ and always asks first. Passwords stay out of the file unless you pass
151
+ `--include-secrets`; a file without passwords still imports, and you re-enter
152
+ each password once afterwards.
153
+
154
+ ---
155
+
156
+ ### Commands reference (`/freeflow`)
157
+
158
+ The same command set works identically in OMP and Pi:
159
+
160
+ ```bash
161
+ /freeflow status # View active relay, pool status, and candidates
162
+ /freeflow list # List all relays with real-time health badges
163
+ /freeflow use <url|index|label> # Switch active relay
164
+ /freeflow url <url> # Set the active relay URL directly
165
+ /freeflow add <url> [label] # Add new relay to the pool
166
+ /freeflow label <index|url> <name># Assign a friendly label to a relay
167
+ /freeflow remove <index|url|label># Remove a relay from the pool
168
+ /freeflow test <index|url|label> # Probe a relay for reachability and latency
169
+ /freeflow on | off | auto # Toggle relay mode (auto = enabled for freeflow)
170
+ /freeflow deploy <platform> # Guided relay deploy: vercel|cloudflare|deno, token in-memory, auto-adds
171
+ /freeflow logs [lines] # Inspect recent proxy logs
172
+ /freeflow trace [req-id] # Tail logs filtered by request correlation ID
173
+ /freeflow refresh # Reload the model catalog from live upstreams
174
+ /freeflow update # Check for and install a package update
175
+ /freeflow debug on | off # Toggle full HTTP lifecycle debug logging
176
+ /freeflow kill # Stop the shared proxy daemon now (restarts on next use)
177
+ /freeflow cline login # Sign in through the browser, save to the per-user pool
178
+ /freeflow cline accounts # List saved Cline logins
179
+ /freeflow cline logout # Remove a saved Cline login
180
+ /freeflow cline signout # Link to sign out of Cline in your browser (to add another account)
181
+ /freeflow export [path] [--include-secrets] # Save the relay pool to a file (default freeflow-relays.json; passwords left out unless asked)
182
+ /freeflow import <path> [--merge|--replace] [--dry-run] # Load a relay pool from a file (merge is default; replace asks first; dry-run previews only)
183
+ ```
184
+
185
+ ---
186
+
187
+ ### 33 models, one command
188
+
189
+ ```bash
190
+ /model → freeflow → pick
191
+ ```
192
+
193
+ #### OpenCode Zen (9 models), Responses and Chat API
194
+
195
+ Good defaults for long coding sessions and agentic work.
196
+
197
+ | Model ID | Creator / Lab | Context | Max Output | Thinking | Vision |
198
+ | :--- | :--- | :--- | :--- | :--- | :--- |
199
+ | `muse-spark-1.2-contributor-free` | Meta Superintelligence Labs | **1M** (1.048.576) | **131K** (131.072) | `minimal … xhigh` | ✅ |
200
+ | `muse-spark-1.3-contributor-free` | Meta Superintelligence Labs | **1M** (1.048.576) | **131K** (131.072) | `minimal … xhigh` | ✅ |
201
+ | `mimo-v2.5-free` | Xiaomi MiMo | **1M** (1.048.576) | **131K** (131.072) | `minimal … xhigh`\* | ✅ |
202
+ | `mimo-v2.6-flash-free` | Xiaomi MiMo | **1M** (1.048.576) | **131K** (131.072) | `minimal … xhigh`\* | ✅ |
203
+ | `nemotron-3.5-lightning-free` | NVIDIA | **1M** (1.000.000) | **262K** (262.144) | `minimal … xhigh` | ❌ |
204
+ | `nemotron-3-ultra-free` | NVIDIA | **1M** (1.000.000) | **128K** (128.000) | `minimal … xhigh` | ❌ |
205
+ | `big-pickle` | Big Pickle | **200K** (200.000) | **32K** (32.000) | `high / max` | ❌ |
206
+ | `ling-3.0-flash-fin-free` | Inclusion AI | **262K** (262.144) | **131K** (131.072) | `minimal … xhigh` | ❌ |
207
+ | `space-bunny-free` | Stealth preview (lab undisclosed) | **1M** (1.048.576) | **512K** (524.288) | `low … max` | ✅ |
208
+
209
+ #### KiloCode Gateway (19 models), OpenRouter compatible
210
+
211
+ Keyless access. Short aliases work for every row (the full ID is in parentheses).
212
+
213
+ | Model ID | Creator / Lab | Context | Max Output | Thinking | Vision |
214
+ | :--- | :--- | :--- | :--- | :--- | :--- |
215
+ | `dots-3-note-preview` (`dots-studio/...:free`) | Dots Studio | **512K** (512.000) | **512K** (512.000) | `minimal…xhigh`\* | ✅ |
216
+ | `nemotron-3-nano-omni` (`nvidia/...:free`) | NVIDIA | **256K** (256.000) | **131K** (131.072) | `minimal…xhigh`\* | ✅ |
217
+ | `nemotron-3-ultra-550b` (`nvidia/...:free`) | NVIDIA | **1M** (1.000.000) | **128K** (128.000) | `minimal…xhigh`\* | ❌ |
218
+ | `nvidia/nemotron-3.5-lightning:free` | NVIDIA | **1M** (1.000.000) | **262K** (262.144) | `minimal…xhigh`\* | ❌ |
219
+ | `nemotron-3-super` (`nvidia/...:free`) | NVIDIA | **262K** (262.144) | **262K** (262.144) | `minimal…xhigh`\* | ❌ |
220
+ | `north-mini-code` (`cohere/...:free`) | Cohere | **256K** (256.000) | **64K** (64.000) | `minimal…xhigh`\* | ❌ |
221
+ | `laguna-s-2.1:free` (`poolside/...:free`) | Poolside | **262K** (262.144) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
222
+ | `laguna-xs-2.1:free` (`poolside/...:free`) | Poolside | **262K** (262.144) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
223
+ | `lfm-2.5` (`liquid/lfm-2.5-2.6b:free`) | Liquid AI | **65K** (65.536) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
224
+ | `kilo-auto` (`kilo-auto/free`) | Kilo Gateway Auto | **256K** (256.000) | **10K** (10.000) | `minimal…xhigh`\* | ❌ |
225
+ | `openrouter` (`openrouter/free`) | OpenRouter Free | **200K** (200.000) | **65K** (65.536) | `minimal…xhigh`\* | ✅ |
226
+ | `content-safety` (`nvidia/...:free`) | NVIDIA | **128K** (128.000) | **8K** (8.192) | ❌ *(non-thinking)* | ✅ |
227
+ | `ling-3.0-flash-fin` (`inclusionai/ling-3.0-flash-fin:free`) | Inclusion AI | **262K** (262.144) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
228
+ | `ling-3.0-flash-sante` (`inclusionai/ling-3.0-flash-sante:free`) | Inclusion AI | **262K** (262.144) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
229
+ | `nex-n2.5-pro` (`nex-agi/nex-n2.5-pro:free`) | Nex AGI | **262K** (262.144) | **235K** (235.929) | `minimal…xhigh`\* | ✅ |
230
+ | `nex-n2.5-mini` (`nex-agi/nex-n2.5-mini:free`) | Nex AGI | **262K** (262.144) | **235K** (235.929) | `minimal…xhigh`\* | ✅ |
231
+ | `inkling-small` (`thinkingmachines/inkling-small:free`) | Thinking Machines | **1M** (1.048.576) | **262K** (262.144) | `minimal…xhigh`\* | ✅ |
232
+ | `qwen3.8-27b` (`qwen/...:free`) | Alibaba Qwen | **262K** (262.144) | **235K** (235.929) | `minimal…xhigh`\* | ✅ |
233
+ | `glm-5.2` (`z-ai/...:free`) | Zhipu AI | **32K** (32.768) | **29K** (29.491) | `minimal…xhigh`\* | ❌ |
234
+
235
+ \* Levels are forwarded as-is through the OpenRouter-style nested `reasoning` parameter; effort mapping is decided by each model. MiMo collapses `minimal→low` and `xhigh→high` upstream, so its selector shows 5 labels but only 3 distinct effort values.
236
+
237
+ #### Cline (5 models), OpenAI compatible
238
+
239
+ Rotating per-account promo, direct only (never through the relay pool). Sign in through your browser with `/freeflow cline login`, manage with `/freeflow cline accounts` and `/freeflow cline logout`. Requests roll across saved logins when one hits its daily free limit.
240
+
241
+ Add as many logins as you want — each one gets its own slot (`default`, `slot-2`, `slot-3`, …) and a request that hits a limit on one rolls straight to the next. To sign in with a different email, sign out of Cline in that browser first (`/freeflow cline signout` prints the link), or use a private window so your current session stays put.
242
+
243
+ Each account can only be saved once: an extra login for an account you already have shares the same free quota, so it is refused rather than saved. If a pool already holds two logins for one account (saved before this check), `/freeflow cline accounts` marks the later one `— same account as [default]`, and `/freeflow cline logout <slot>` drops it.
244
+
245
+ | Model ID | Creator / Lab | Context | Max Output | Thinking | Vision |
246
+ | :--- | :--- | :--- | :--- | :--- | :--- |
247
+ | `cline-free/deepseek-v4.1-flash` | DeepSeek | **1M** (1.000.000) | **384K** (384.000) | `low/high/max` | ✅ |
248
+ | `cline-free/muse-spark-1.3-contributor` | Meta Superintelligence Labs | **1M** (1.048.576) | **131K** (131.072) | `minimal…xhigh`\* | ✅ |
249
+ | `z-ai/glm-5.3-flash` | Zhipu AI | **1M** (1.000.000) | **131K** (131.072) | `low/high/max` | ✅ |
250
+ | `cline-free/kimi-k3` | Moonshot AI | **1M** (1.048.576) | **131K** (131.072) | `low/high/max` | ✅ |
251
+ | `cline-free/solar-pro4` | Upstage | **512K** (524.288) | **131K** (131.072) | `minimal…max`\* | ❌ |
252
+
253
+ ---
254
+
255
+ ### Logs and debugging
256
+
257
+ ```bash
258
+ /freeflow logs
259
+ cat ~/.pi/agent/pi-freeflow.log | tail -n 50
260
+
261
+ # full debug logging is on by default; `off` restores info level
262
+ /freeflow debug on
263
+ ```
264
+
265
+ ---
266
+
267
+ ### Design
268
+
269
+ This package stays thin. It ships three things: a model catalog, a relay proxy, and a log. There is no build step and zero runtime dependencies. Thinking and prompt normalization stay with the host (`pi-ai`).
270
+
271
+ About 19k lines including tests. The full suite (sandboxed, network-mocked) and typecheck pass before every release. See CHANGELOG.md.
272
+
273
+ ---
274
+
275
+ ### FAQ
276
+
277
+ **Do I need API keys?**
278
+ No. Kilo uses a shared free credential and OpenCode free models need no header. You never paste a key. Cline free models need a browser login instead: `/freeflow cline login` saves it to a per-user pool on your machine.
279
+
280
+ **What if all relays hit rate limits?**
281
+ The proxy tries direct upstream. If that is also rate-limited, the host shows the limit. That number is the shared upstream cap; without relays you would hit the same wall sooner.
282
+
283
+ **Can I use it without relays?**
284
+ Yes. `/freeflow off` talks direct. Add relays later when you need them.
285
+
286
+ **What happens when I update to a new version?**
287
+ The local proxy daemon is shared across sessions on port 28180. On upgrade, the new extension
288
+ detects a stale daemon (an older version still running) and replaces it automatically, with no manual
289
+ kill and no restart of other sessions. Replacement only happens when the running daemon is
290
+ idle: sessions with in-flight requests are never interrupted (busy or newer daemons are reused
291
+ with a log note instead). If a daemon cannot be replaced (for example the port is held by an unrelated process),
292
+ it falls back to reusing it with a warning. To disable replacement entirely, set the no-kill env
293
+ to `1` before starting a session.
294
+
295
+ **What happens when I close a session?**
296
+ Nothing visible to your other sessions. The proxy daemon is a separate background
297
+ process shared by every OMP/Pi session on the machine. Closing one session just
298
+ unregisters it; the daemon keeps serving the rest and retires itself automatically
299
+ once the last client disconnects and no client re-attaches within a short grace window.
300
+ To stop it manually, run `/freeflow kill`. The next freeflow use starts it again.
301
+
302
+ **Why did my long session stop with a "reasoning was not issued to this caller" error?**
303
+ The upstream backend signs each thinking block so only the backend that produced it can read it back. When a later turn reaches a different backend, the old blocks get rejected and the session stalls. pi-freeflow keeps each conversation on the relay that produced its thinking while that relay is healthy. When the relay has to change anyway (rate limit, relay removed, direct-mode switch), that turn is sent without the old thinking blocks so the new backend accepts it, and only the rejected blocks are dropped afterwards. Messages, tool calls, and tool results are always kept.
304
+
305
+ **Why is it installed via npm?**
306
+ The npm package is the distribution channel only. Both hosts resolve it internally:
307
+ `omp plugin install pi-freeflow` and `pi install npm:pi-freeflow` install the same
308
+ package from the npm registry. pi-freeflow is an extension, not a standalone CLI.
309
+ The host (OMP or Pi) loads and runs it. A plain `npm install` just downloads the
310
+ files; it is not a supported way to run the extension.
311
+
312
+ **Which hosts can use it?**
313
+ Oh My Pi (OMP) and Pi only. They share the same extension API, so one
314
+ package serves both. Other AI agents (OpenCode, KiloCode, Cursor, and similar) have their
315
+ own plugin systems and do not load this extension.
316
+
317
+ ---
318
+
319
+ ### Contributing
320
+
321
+ Contributions welcome: bug fixes, new relay platforms, model additions, docs improvements.
322
+
323
+ #### Prerequisites
324
+
325
+ - **Node.js ≥ 22.19.0** (uses `--experimental-strip-types`, no build step)
326
+ - **pnpm** (package manager)
327
+
328
+ #### Setup and verify
329
+
330
+ ```bash
331
+ git clone https://github.com/trefeon/pi-freeflow
332
+ cd pi-freeflow
333
+ pnpm install
334
+
335
+ # run all three before opening a PR
336
+ pnpm test # full suite; sandboxed and network-mocked
337
+ pnpm typecheck # tsc --noEmit, must pass clean
338
+ pnpm smoke # verifies extensions/index.ts loads without crashing
339
+ ```
340
+
341
+ #### Project structure
342
+
343
+ ```
344
+ src/
345
+ ├── index.ts # extension entry, lifecycle hooks
346
+ ├── models.ts # 33-model catalog definitions
347
+ ├── catalog.ts # model catalog cache (24h disk)
348
+ ├── proxy.ts # local proxy server (127.0.0.1:28180)
349
+ ├── relay.ts # relay selection and round-robin
350
+ ├── relay-state.ts # relay pool state, health tracking
351
+ ├── stream-pipe.ts # SSE stream piping and truncation resilience
352
+ ├── commands.ts # /freeflow CLI subcommands
353
+ ├── deploy.ts # guided relay deploy (vercel/cloudflare/deno)
354
+ ├── config.ts # constants, whitelists, paths, and runtime settings
355
+ ├── logger.ts # file logger with 10MB rotation
356
+ └── types.ts # shared type definitions
357
+ extensions/
358
+ └── index.ts # OMP/Pi extension manifest
359
+ test/
360
+ └── *.test.ts # mirrors src/, node:test runner
361
+ ```
362
+
363
+ #### Guidelines
364
+
365
+ - **Stay thin.** Zero runtime dependencies, no build step. If it belongs in the host (`pi-ai`), don't add it here.
366
+ - **Test what you touch.** Every `src/*.ts` has a matching `test/*.test.ts`. Add or update tests for your change.
367
+ - **Keep model IDs clean.** Slash-free, colon-free aliases for CLI compatibility. See existing patterns in `models.ts`.
368
+ - **One concern per PR.** Bug fix? One PR. New relay platform? Separate PR. Easier to review, faster to merge.
369
+
370
+ #### Reporting issues
371
+
372
+ Found a bug or want a feature? [Open an issue](https://github.com/trefeon/pi-freeflow/issues) with:
373
+ - What happened vs what you expected
374
+ - Your relay setup (`/freeflow status` output helps)
375
+ - Relevant logs (`/freeflow logs` or `~/.pi/agent/pi-freeflow.log`)
376
+
377
+ ---
378
+
379
+ ### License
380
+
381
+ MIT © trefeon