@zenithfoundry/slm-gate 1.2.1
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/.env.example +669 -0
- package/LICENSE +21 -0
- package/README.md +317 -0
- package/configs/antigravity/.env.16gb.example +674 -0
- package/configs/antigravity/.env.24gb.example +674 -0
- package/configs/antigravity/.env.32gb.example +674 -0
- package/configs/antigravity/README.md +109 -0
- package/configs/claude-code/.env.16gb.example +674 -0
- package/configs/claude-code/.env.24gb.example +674 -0
- package/configs/claude-code/.env.32gb.example +674 -0
- package/configs/claude-code/README.md +52 -0
- package/configs/claude-desktop/.env.16gb.example +674 -0
- package/configs/claude-desktop/.env.24gb.example +674 -0
- package/configs/claude-desktop/.env.32gb.example +674 -0
- package/configs/claude-desktop/README.md +37 -0
- package/configs/cline-continue-opencode/.env.16gb.example +674 -0
- package/configs/cline-continue-opencode/.env.24gb.example +674 -0
- package/configs/cline-continue-opencode/.env.32gb.example +674 -0
- package/configs/cline-continue-opencode/README.md +34 -0
- package/configs/cursor/.env.16gb.example +674 -0
- package/configs/cursor/.env.24gb.example +674 -0
- package/configs/cursor/.env.32gb.example +674 -0
- package/configs/cursor/README.md +26 -0
- package/configs/generic-http/.env.16gb.example +674 -0
- package/configs/generic-http/.env.24gb.example +674 -0
- package/configs/generic-http/.env.32gb.example +674 -0
- package/configs/generic-http/README.md +20 -0
- package/configs/generic-stdio/.env.16gb.example +674 -0
- package/configs/generic-stdio/.env.24gb.example +674 -0
- package/configs/generic-stdio/.env.32gb.example +674 -0
- package/configs/generic-stdio/README.md +24 -0
- package/configs/preserve/README.md +26 -0
- package/configs/preserve/tls.json +61 -0
- package/dist/adapters/tech-lead-stack.js +38 -0
- package/dist/cache/index.js +173 -0
- package/dist/cli.js +256 -0
- package/dist/config.js +255 -0
- package/dist/dashboard/data.js +149 -0
- package/dist/dashboard/export.js +42 -0
- package/dist/dashboard/serve.js +63 -0
- package/dist/doctor.js +338 -0
- package/dist/hardware.js +126 -0
- package/dist/home-dir.js +39 -0
- package/dist/ledger/flush-lifecycle.js +50 -0
- package/dist/ledger/index.js +946 -0
- package/dist/ledger/report.js +69 -0
- package/dist/ledger/setup-dashboard.js +456 -0
- package/dist/ledger/smoke.js +37 -0
- package/dist/ledger/sync-config.js +177 -0
- package/dist/ledger/sync.js +307 -0
- package/dist/ledger/verify.js +185 -0
- package/dist/ledger/wipe-langfuse.js +130 -0
- package/dist/llm-gate/distill.js +239 -0
- package/dist/llm-gate/formats/anthropic.js +185 -0
- package/dist/llm-gate/formats/chat-completions.js +103 -0
- package/dist/llm-gate/formats/contract.js +29 -0
- package/dist/llm-gate/formats/gemini.js +84 -0
- package/dist/llm-gate/formats/internal.js +1 -0
- package/dist/llm-gate/formats/openai.js +77 -0
- package/dist/llm-gate/formats/responses.js +146 -0
- package/dist/llm-gate/forward.js +150 -0
- package/dist/llm-gate/index.js +40 -0
- package/dist/llm-gate/local-first.js +217 -0
- package/dist/llm-gate/pipeline.js +267 -0
- package/dist/llm-gate/server.js +289 -0
- package/dist/mcp-gate/ground.js +64 -0
- package/dist/mcp-gate/index.js +57 -0
- package/dist/mcp-gate/pipeline.js +252 -0
- package/dist/mcp-gate/server.js +302 -0
- package/dist/mcp-gate/tool-names.js +57 -0
- package/dist/models/check.js +26 -0
- package/dist/models/footprint.js +137 -0
- package/dist/models/helpers.js +91 -0
- package/dist/models/index.js +5 -0
- package/dist/models/reasoning.js +91 -0
- package/dist/models/roles.js +9 -0
- package/dist/models/slm.js +243 -0
- package/dist/models/types.js +1 -0
- package/dist/pricing/index.js +115 -0
- package/dist/pricing/plans.js +54 -0
- package/dist/pricing/providers.js +172 -0
- package/dist/resolver/index.js +277 -0
- package/dist/resolver/types.js +1 -0
- package/dist/setup/claim.js +41 -0
- package/dist/setup/gate-command.js +41 -0
- package/dist/setup/init.js +92 -0
- package/dist/setup/local-models.js +123 -0
- package/dist/setup/model-gate.js +220 -0
- package/dist/setup/notify.js +45 -0
- package/dist/setup/ollama-install.js +53 -0
- package/dist/setup/parent-watch.js +84 -0
- package/dist/setup/required-models.js +20 -0
- package/dist/setup/startup.js +132 -0
- package/dist/setup/tool-settings.js +101 -0
- package/dist/utils/backoff.js +47 -0
- package/dist/utils/compression.js +145 -0
- package/dist/utils/constants.js +22 -0
- package/dist/utils/duration.js +43 -0
- package/dist/utils/elision.js +556 -0
- package/dist/utils/embedding.js +32 -0
- package/dist/utils/entry-point.js +23 -0
- package/dist/utils/local-only.js +82 -0
- package/dist/utils/preserve-patterns.js +115 -0
- package/dist/utils/safety.js +30 -0
- package/dist/verifier/index.js +67 -0
- package/package.json +121 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 bronz3beard
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# slm-gate
|
|
2
|
+
|
|
3
|
+
**Make your AI coding plan last longer.** A small model on your own computer shrinks the large tool output your coding assistant sends to the paid cloud, and answers easy first messages itself. Works with Claude Code, Codex, Cursor, Gemini CLI, Cline and any MCP client. Runs on [Ollama](https://ollama.com/). Free and MIT-licensed.
|
|
4
|
+
|
|
5
|
+
**[See the live savings dashboard →](https://zenithfoundry.github.io/slm-gate/)** Measured from real daily use; benchmark runs are kept separate.
|
|
6
|
+
|
|
7
|
+
[](https://github.com/zenithfoundry/slm-gate/actions/workflows/ci.yml)
|
|
8
|
+
[](https://github.com/zenithfoundry/slm-gate/actions/workflows/codeql.yml)
|
|
9
|
+
[](https://scorecard.dev/viewer/?uri=github.com/zenithfoundry/slm-gate)
|
|
10
|
+
[](LICENSE)
|
|
11
|
+
[](package.json)
|
|
12
|
+
[](https://github.com/zenithfoundry/slm-gate/commits/main)
|
|
13
|
+
<br />
|
|
14
|
+
[](package.json)
|
|
15
|
+
[](tsconfig.json)
|
|
16
|
+
[](https://modelcontextprotocol.io/)
|
|
17
|
+
[](https://ollama.com/)
|
|
18
|
+
[](docs/prerequisites-and-hardware.md)
|
|
19
|
+
[](https://zenithfoundry.github.io/slm-gate/)
|
|
20
|
+
[](https://github.com/zenithfoundry/slm-gate/pulls)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Table of Contents
|
|
25
|
+
|
|
26
|
+
1. [What is slm-gate?](#what-is-slm-gate)
|
|
27
|
+
2. [How It Works: Visual](#how-it-works-visual)
|
|
28
|
+
3. [Quick Start](#quick-start)
|
|
29
|
+
4. [Documentation](#documentation)
|
|
30
|
+
5. [Contributing & Security](#contributing--security)
|
|
31
|
+
6. [Related Project](#related-project)
|
|
32
|
+
7. [Intended Use](#intended-use)
|
|
33
|
+
8. [License](#license)
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## What is slm-gate?
|
|
38
|
+
|
|
39
|
+
`small-language-model-gate` (CLI shortname: **`slm-gate`**) is a **local AI pre-processing and routing layer** that sits in front of your AI coding assistant and quietly does two very useful things before anything reaches the paid cloud:
|
|
40
|
+
|
|
41
|
+
**It compresses the noise.** Your editor constantly packages up huge files, long logs, and sprawling system instructions and sends them to the cloud AI with every single message. Most of that is content the AI skims past. `slm-gate` intercepts this, runs a small, fast, free AI on your own computer, and strips it down to what actually matters — sending a fraction of the original text to the cloud.
|
|
42
|
+
|
|
43
|
+
**It answers easy questions locally.** Many conversations open with something a small model can answer — a quick fact, a short explanation, a greeting. `slm-gate` lets your local model try the first message of each conversation; if its answer passes a check, that request never reaches your paid plan at all. Anything else, and every slash command, goes to the cloud as normal.
|
|
44
|
+
|
|
45
|
+
The result: your paid AI plan lasts dramatically longer. Whether you're on a subscription (Claude Pro, Cursor Pro, Gemini Advanced, ChatGPT Plus) or paying per-token via an API key, you spend far less on the same amount of real work.
|
|
46
|
+
|
|
47
|
+
### Why You Need This
|
|
48
|
+
|
|
49
|
+
Every AI subscription comes with rate limits. Claude Pro's five-hour windows, Cursor's monthly turn caps, ChatGPT Plus's hourly message limits — these aren't just numbers. Hit them mid-project and you're waiting hours to continue. `slm-gate` acts as a buffer. By intercepting routine traffic and compressing what does go to the cloud, your effective quota stretches much further.
|
|
50
|
+
|
|
51
|
+
On pay-per-token API plans (like `gpt-4o` or Claude Sonnet via API key), every token costs money. Sending a 500-line file when the model only needed 30 lines of context is a direct waste of budget. `slm-gate` eliminates that waste automatically.
|
|
52
|
+
|
|
53
|
+
### Key Benefits
|
|
54
|
+
|
|
55
|
+
| Benefit | What It Means For You |
|
|
56
|
+
| :--- | :--- |
|
|
57
|
+
| **Quota Protection** | Fewer turns and tokens consumed means your subscription window lasts longer |
|
|
58
|
+
| **$0 Local Execution** | Small, repetitive queries answered free by your local machine |
|
|
59
|
+
| **Context Compression** | Large files, logs, and tool responses trimmed intelligently before hitting the cloud |
|
|
60
|
+
| **Privacy** | Less of your actual code and data leaves your machine |
|
|
61
|
+
| **Provider-Agnostic** | Works with Claude, GPT, Gemini, or any OpenAI-compatible endpoint |
|
|
62
|
+
|
|
63
|
+
### What Gets Measured: Your Savings Dashboard
|
|
64
|
+
|
|
65
|
+
`slm-gate` records every decision it makes in a local database file on your computer (a SQLite database — think of it as a simple, fast spreadsheet that lives on your machine). For every request, it logs:
|
|
66
|
+
|
|
67
|
+
- How many tokens (units of text) were in the original payload
|
|
68
|
+
- How many tokens remained after compression
|
|
69
|
+
- Whether the request was answered locally (free) or forwarded to the cloud (answering locally is `llm-gate` only; see [How It Operates](docs/integration-layers.md))
|
|
70
|
+
- How long the local processing took
|
|
71
|
+
- The simulated dollar cost saved (for API key users)
|
|
72
|
+
|
|
73
|
+
**Checking your savings is one command:**
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pnpm run slm-gate metrics
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
This prints a clean, offline summary showing tokens saved, compression ratio, requests handled locally, and how many extra minutes of subscription headroom you've gained — no API keys, no internet connection required.
|
|
80
|
+
|
|
81
|
+
**Want a visual dashboard?** Run `pnpm run dashboard` for the built-in one-page dashboard — per-cycle window time returned per provider, tokens saved, weekly charts and routing split, straight from the local ledger, publishable to GitHub Pages for free (see [The Metrics Dashboard](docs/daily-use.md#the-metrics-dashboard)). If you also set up [Langfuse](https://langfuse.com/) (a free, open-source observability tool), `slm-gate` will send traces there for session-by-session analysis. Both are optional — the local metrics command always works regardless.
|
|
82
|
+
|
|
83
|
+
### How It Works: Visual
|
|
84
|
+
|
|
85
|
+
Five small diagrams, each answering one question. Read them in order. Numbers on the arrows show the order things happen.
|
|
86
|
+
|
|
87
|
+
#### 1. The big picture
|
|
88
|
+
|
|
89
|
+
slm-gate is two small servers on your computer, between your coding tool and the outside world. Both use small local models, run by Ollama:
|
|
90
|
+
|
|
91
|
+
- **Tool calls** go through the **MCP gate**. It passes each call to your toolbox, then trims long text in the result before your coding tool sees it: fixed rules first, then the small model summarises what is still too long. It also adds a short note on what your project uses, and lists any open decisions it found in the text, answered where it can.
|
|
92
|
+
- **Model requests** go through the **model gate**. On the first message of a conversation, the small model may answer by itself, and then the cloud is never called. Otherwise the gate shrinks new command, search and listing output, and sends the request to your AI provider with your own login.
|
|
93
|
+
|
|
94
|
+
If the small model fails or runs out of time, the text it was working on goes on as it was. Both gates record what they did in a local ledger (diagram 5).
|
|
95
|
+
|
|
96
|
+
```mermaid
|
|
97
|
+
flowchart LR
|
|
98
|
+
tool(("Coding tool"))
|
|
99
|
+
|
|
100
|
+
subgraph mcpRow["Tool calls: MCP gate"]
|
|
101
|
+
direction LR
|
|
102
|
+
mcp["MCP gate"] -->|"pass on"| toolbox["Downstream MCP<br/>toolbox"]
|
|
103
|
+
toolbox -->|"raw result"| trim["MCP gate trims long text:<br/>rules first, then small model"]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
subgraph llmRow["Model requests: model gate"]
|
|
107
|
+
direction LR
|
|
108
|
+
llm["Model gate"] -->|"first message"| answer["Small model<br/>tries to answer"]
|
|
109
|
+
llm -->|"later messages"| shrink["Shrink new command,<br/>search and listing output"]
|
|
110
|
+
answer -->|"no answer"| shrink
|
|
111
|
+
shrink --> cloud["Your AI provider<br/>(your login or API key)"]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
tool --> mcp
|
|
115
|
+
trim -->|"smaller result"| tool
|
|
116
|
+
tool --> llm
|
|
117
|
+
answer -.->|"answer passed the check:<br/>reply, no cloud call"| tool
|
|
118
|
+
cloud -->|"reply, back through<br/>the gate unchanged"| tool
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
#### 2. What happens to a tool call (MCP gate)
|
|
122
|
+
|
|
123
|
+
The MCP gate passes each tool call to your downstream toolbox unchanged. When the result comes back, it works on the text only: pictures, structured data and the error flag go back as the toolbox sent them. The gate also adds one tool of its own, `expand_elision`, which fetches back any lines it cut. With no toolbox set, the gate offers a single tool instead, `condition_prompt`, which runs the same steps on text you send it.
|
|
124
|
+
|
|
125
|
+
```mermaid
|
|
126
|
+
flowchart LR
|
|
127
|
+
tool(("Coding tool"))
|
|
128
|
+
server["MCP server<br/>[mcp-gate/server.ts]"]
|
|
129
|
+
toolbox["Downstream MCP"]
|
|
130
|
+
cond["Condition the text<br/>[mcp-gate/pipeline.ts]"]
|
|
131
|
+
helpers["In order: saved result?,<br/>trim, project scan,<br/>open decisions"]
|
|
132
|
+
ledger[("Ledger")]
|
|
133
|
+
paid["Cloud model<br/>(CLOUD_API_KEY)"]
|
|
134
|
+
|
|
135
|
+
tool -->|"1. tool call"| server
|
|
136
|
+
server -->|"2. pass it on"| toolbox
|
|
137
|
+
toolbox -->|"3. raw result"| server
|
|
138
|
+
server -->|"4. text only"| cond
|
|
139
|
+
cond -->|"5. uses"| helpers
|
|
140
|
+
cond -->|"6. log it"| ledger
|
|
141
|
+
server -->|"7. smaller result"| tool
|
|
142
|
+
helpers -.->|"optional, off by default"| paid
|
|
143
|
+
tool -.->|"later: expand_elision"| server
|
|
144
|
+
ledger -.->|"the cut lines"| server
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
| Step | File | What it does |
|
|
148
|
+
| :--- | :--- | :--- |
|
|
149
|
+
| Saved result | `src/ledger/index.ts`; `src/cache/index.ts` with `SEMCACHE=on` | If the same tool returned the same text before, sends the saved result and skips the steps below. With `SEMCACHE=on`, very similar text counts too. |
|
|
150
|
+
| Trim | `src/utils/elision.ts` | Leaves text under `DISTILL_MIN_TOKENS` alone. Otherwise saves the original for `expand_elision`, then cuts by tool name: a file keeps its outline and the lines about the task, a log keeps its errors and last 50 lines, a search keeps its first 50 lines. If it is still over `DISTILL_MAX_TOKENS`, the gate model summarises the plain prose, never code blocks, tables, headings or protected lines (and, by default, never skills or file reads). Anything still too long keeps only its start and end. |
|
|
151
|
+
| Project scan | `src/mcp-gate/ground.ts` | Reads the project's root files (`package.json`, `tsconfig.json`, lockfiles, `Cargo.toml`, `go.mod`) and adds a short list of what the project uses. Only when your coding tool shares the project folder. |
|
|
152
|
+
| Open decisions | `src/resolver/index.ts` | The brain model lists up to 3 open decisions in the text and answers each from your project's files or common practice; the gate model rates each one's risk. Low-risk answers found in your files are added as decided; the rest are added as questions to ask you, with a suggested answer. With `RESOLVER_CLOUD_TIER=on` and a budget set, unsure ones go to a paid cloud model using `CLOUD_API_KEY`. |
|
|
153
|
+
|
|
154
|
+
#### 3. What happens to a model request (model gate)
|
|
155
|
+
|
|
156
|
+
The model gate is a small server at `http://localhost:8787`. It reads four request formats (Anthropic Messages, OpenAI Chat Completions, OpenAI Responses and Gemini) and makes two tries to save you money before anything goes to your AI provider:
|
|
157
|
+
|
|
158
|
+
- **Step A, answer locally** (first message of a conversation only). Skipped for slash commands, for requests that demand a set output format or a tool call, and, when the coding tool offers the model tools, for messages that mention your code or files or ask about the assistant itself. Otherwise the gate model sorts the question by type, and only simple types are tried: short facts and formatting, plus yes/no, extraction, classification and spelling fixes when no tools are offered. The brain model answers 3 times by default, and the verifier (`src/verifier/index.ts`) rejects an empty answer, a hedging one ("I'm not sure") or answers that disagree. A passing answer goes back in the provider's own format and the cloud is never called. One try at a time, at most 6 seconds. `SEMCACHE=on` also reuses a saved answer to a very similar question, and `ROUTING_TUNE=on` stops trying types that usually fail.
|
|
159
|
+
- **Step B, shrink** (every request not answered locally). New command, search and listing output of at least `DISTILL_MIN_TOKENS` is trimmed the same way as in the MCP gate. File reads (including `cat` and similar run from a shell), web fetches and MCP tool results are never changed. Each decision is saved and resent unchanged on every later turn, so the provider's prompt cache keeps working. At most 3 seconds; after that, the original goes.
|
|
160
|
+
|
|
161
|
+
The request then goes to the provider its address belongs to, with every header your coding tool sent, so your own subscription login or API key is used; slm-gate never adds or swaps credentials. The reply streams back unchanged. Token counts, model lists and hello pings skip both steps.
|
|
162
|
+
|
|
163
|
+
```mermaid
|
|
164
|
+
flowchart LR
|
|
165
|
+
tool(("Coding tool"))
|
|
166
|
+
server["Model gate<br/>[llm-gate/server.ts]"]
|
|
167
|
+
stepA["Step A: answer locally?<br/>[llm-gate/local-first.ts]"]
|
|
168
|
+
stepB["Step B: shrink new output<br/>[llm-gate/distill.ts]"]
|
|
169
|
+
fwd["Forward<br/>[llm-gate/forward.ts]"]
|
|
170
|
+
cloud["Your AI provider<br/>(your login or API key)"]
|
|
171
|
+
ledger[("Ledger")]
|
|
172
|
+
|
|
173
|
+
tool -->|"1. request"| server
|
|
174
|
+
server -->|"2. first message only"| stepA
|
|
175
|
+
stepA -.->|"passed the check: reply now"| tool
|
|
176
|
+
server -->|"3. not answered locally"| stepB
|
|
177
|
+
stepB -->|"4. smaller request"| fwd
|
|
178
|
+
fwd -->|"5. same headers"| cloud
|
|
179
|
+
cloud -->|"6. reply"| fwd
|
|
180
|
+
fwd -->|"7. reply, unchanged"| tool
|
|
181
|
+
server -->|"8. log it"| ledger
|
|
182
|
+
stepB -.->|"saved decisions"| ledger
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### 4. How it starts, and what the CLI does
|
|
186
|
+
|
|
187
|
+
You rarely start anything by hand. Your coding tool starts the MCP gate. Before the MCP gate answers the tool (it waits at most 1.5 seconds), it starts the model gate in the background if nothing is running on its port, and checks that Ollama is running and every model your settings name is downloaded. It checks again 15 seconds later and then every minute, restarting the model gate if it stopped, unless you stopped it with `slm-gate stop`. With `LLM_GATE_AUTOSTART=off` it never starts the model gate and only checks once. It never starts Ollama or downloads a model. Problems show up as a desktop notification, and problems found at start-up are also passed to your AI assistant. The CLI is for doing this by hand, and for checks and reports.
|
|
188
|
+
|
|
189
|
+
```mermaid
|
|
190
|
+
flowchart LR
|
|
191
|
+
tool(("Coding tool"))
|
|
192
|
+
you(("You"))
|
|
193
|
+
mcp["MCP gate<br/>[mcp-gate/index.ts]"]
|
|
194
|
+
checks["Start-up checks<br/>[setup/startup.ts]"]
|
|
195
|
+
ollama["Ollama"]
|
|
196
|
+
llm["Model gate<br/>[llm-gate/index.ts]"]
|
|
197
|
+
cli["CLI<br/>[cli.ts]"]
|
|
198
|
+
|
|
199
|
+
tool -->|"1. starts"| mcp
|
|
200
|
+
mcp -->|"2. at start, after 15 s,<br/>then every minute"| checks
|
|
201
|
+
checks -->|"3. running? models downloaded?"| ollama
|
|
202
|
+
checks -->|"4. start it if not running"| llm
|
|
203
|
+
checks -.->|"problems: desktop notification"| you
|
|
204
|
+
checks -.->|"problems at start:<br/>told to your AI assistant"| tool
|
|
205
|
+
you --> cli
|
|
206
|
+
cli -->|"start, stop, restart, serve"| llm
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
| Command | Runs | Does |
|
|
210
|
+
| :--- | :--- | :--- |
|
|
211
|
+
| `start`, `stop`, `restart` | `src/setup/gate-command.ts` | Starts or stops the background model gate; `stop` lasts until `start`, `restart` or a reboot |
|
|
212
|
+
| `serve` | `src/llm-gate/index.ts` | Runs the model gate in this terminal (`--layer mcp` or `both` runs the MCP gate too) |
|
|
213
|
+
| `doctor` | `src/doctor.ts` | Preflight checks, and the exact line to paste into each coding tool |
|
|
214
|
+
| `config` | `src/config.ts` | Prints your settings |
|
|
215
|
+
| `models:check` | `src/models/check.ts` | Checks your models are downloaded and fit in memory |
|
|
216
|
+
| `metrics` | `harness/metrics.ts` | Rows, tokens and cost in the ledger, gate on vs off |
|
|
217
|
+
| `ledger:sync` | `src/ledger/sync.ts` | Sends ledger history to Langfuse |
|
|
218
|
+
| `setup-dashboard` | `src/ledger/setup-dashboard.ts` | Builds the Langfuse dashboard |
|
|
219
|
+
| `ledger:reset` | `src/cli.ts` | Deletes the local ledger and benchmark output |
|
|
220
|
+
| `bench` | `harness/run.ts` | Offline benchmark with an API key (not live traffic) |
|
|
221
|
+
|
|
222
|
+
#### 5. Where the data goes
|
|
223
|
+
|
|
224
|
+
Both gates write one row to the local ledger, a SQLite file (`output/ledger.sqlite` by default): one for each tool result the MCP gate conditions, and one for each model request the model gate answers or forwards. A row holds token counts, the route taken and timings, not the text itself. Rows for your coding tool's traffic carry no price; only the optional resolver cloud call and the benchmark record one. Cost saved (from the price list) and minutes saved (from each provider's usage-window size) are worked out for Langfuse as each row is written and again by `ledger:sync`; the dashboard works out minutes saved each time it loads. The same file also keeps saved results, the original of anything cut (for `expand_elision`), and the model gate's shrink decisions.
|
|
225
|
+
|
|
226
|
+
If all three Langfuse keys are set, each gate sends its new rows there as it runs (at start-up, every 15 seconds and at shutdown), and `ledger:sync` re-sends history.
|
|
227
|
+
|
|
228
|
+
```mermaid
|
|
229
|
+
flowchart LR
|
|
230
|
+
gates["Both gates"]
|
|
231
|
+
ledger[("Ledger<br/>[ledger/index.ts]")]
|
|
232
|
+
pricing["Prices and window sizes<br/>[pricing/]"]
|
|
233
|
+
metrics["slm-gate metrics<br/>[harness/metrics.ts]"]
|
|
234
|
+
report["Tokens saved per day<br/>[ledger/report.ts]"]
|
|
235
|
+
dash["Dashboard<br/>[dashboard/serve.ts]"]
|
|
236
|
+
site["site/ folder for GitHub Pages<br/>[dashboard/export.ts]"]
|
|
237
|
+
langfuse["Langfuse (optional)"]
|
|
238
|
+
|
|
239
|
+
gates -->|"1. a row per request"| ledger
|
|
240
|
+
ledger --> metrics
|
|
241
|
+
ledger --> report
|
|
242
|
+
ledger --> dash
|
|
243
|
+
ledger --> site
|
|
244
|
+
pricing -->|"minutes saved"| dash
|
|
245
|
+
pricing -->|"cost and minutes saved"| langfuse
|
|
246
|
+
ledger -.->|"new rows every 15 s;<br/>ledger:sync for history"| langfuse
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
| Reader | Command | Shows |
|
|
250
|
+
| :--- | :--- | :--- |
|
|
251
|
+
| Metrics | `slm-gate metrics` | Rows, tokens and cost, gate on vs off |
|
|
252
|
+
| Report | `pnpm run ledger:report` | Tokens saved per day and all-time |
|
|
253
|
+
| Dashboard | `pnpm run dashboard` | Minutes of each provider's usage window returned, tokens saved, weekly charts, routing split, local-answer accuracy |
|
|
254
|
+
| Static copy | `pnpm run dashboard:export` | The dashboard with numbers and dates only, written to `site/` for the Pages workflow |
|
|
255
|
+
| Langfuse | runs by itself; `slm-gate ledger:sync` for history | A trace per request, with cost, tokens and minutes saved |
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Quick Start
|
|
260
|
+
|
|
261
|
+
You need Node.js 22+, pnpm 10+ and [Ollama](https://ollama.com/download) running. This is the setup for a 16 GB machine with Claude Code; other editors and machine sizes are in the [setup guide](docs/setup.md).
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
git clone https://github.com/zenithfoundry/slm-gate.git small-language-model-gate
|
|
265
|
+
cd small-language-model-gate
|
|
266
|
+
pnpm install && pnpm run build
|
|
267
|
+
cp configs/claude-code/.env.16gb.example .env
|
|
268
|
+
ollama pull qwen2.5-coder:3b && ollama pull qwen2.5-coder:0.5b
|
|
269
|
+
claude mcp add --scope user slm-gate -- node "$PWD/dist/mcp-gate/index.js"
|
|
270
|
+
node dist/cli.js doctor
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Then restart Claude Code. `doctor` checks Ollama, your models and the model gate, and prints the one line to add to Claude Code's settings if you also want its model requests to go through the gate ([Layer 2](docs/integration-layers.md#layer-2-llm-gate--the-model-endpoint-proxy)).
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Documentation
|
|
278
|
+
|
|
279
|
+
Setup and reference guides live in [`docs/`](docs/README.md). The first time through, read them in this order:
|
|
280
|
+
|
|
281
|
+
1. [Prerequisites & Hardware Sizing](docs/prerequisites-and-hardware.md): what to install, and which local models fit your machine's memory
|
|
282
|
+
2. [How It Operates](docs/integration-layers.md): the two layers, who pays for what, and which coding tools work with each
|
|
283
|
+
3. [Step-by-Step Setup](docs/setup.md): clone, build, download models, and connect your editor
|
|
284
|
+
4. [Configuration](docs/configuration.md): RAM presets, the 16 GB baseline `.env`, and every setting explained
|
|
285
|
+
5. [Verification & Day-to-Day Use](docs/daily-use.md): the health check, fixing start-up problems, checking savings, the dashboard
|
|
286
|
+
6. [Architecture & Advanced Features](docs/advanced.md): the hosted small-model fallback, and a rule for contributors
|
|
287
|
+
|
|
288
|
+
Also: [walkthroughs](docs/README.md#walkthroughs), [analytics & observability](docs/analytics-and-observability.md), [architecture overview](ARCHITECTURE.md), and [every doc on one page](docs/README.md).
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Contributing & Security
|
|
293
|
+
|
|
294
|
+
Pull requests are welcome; read the [contributing guide](.github/CONTRIBUTING.md) first. For help, and what is supported, see [support](SUPPORT.md). Please report security problems privately, as the [security policy](SECURITY.md) describes, not in a public issue.
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Related Project
|
|
299
|
+
|
|
300
|
+
> [!NOTE]
|
|
301
|
+
> **Tech-Lead-Stack:** An agent-agnostic library of Markdown "skills" plus an MCP
|
|
302
|
+
> server that turns Claude, Gemini, or GPT into a full software-delivery team (planning,
|
|
303
|
+
> building, review, security, release), organized around a nine-phase lifecycle. Its
|
|
304
|
+
> self-correcting Reflexion loop grades implementation plans against four engineering
|
|
305
|
+
> pillars before any code is written. `slm-gate` can sit in front of it and shrink its skill payloads.
|
|
306
|
+
>
|
|
307
|
+
> <a href="https://github.com/bronz3beard/ai.tech-lead-stack" target="_blank" rel="noopener noreferrer">Explore tech-lead-stack on GitHub →</a>
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## Intended Use
|
|
312
|
+
|
|
313
|
+
This software runs locally and drives third-party AI tools and models that **you** install and authenticate. You are responsible for complying with the terms of any tool, model, or subscription you connect to it. It is designed for single-user, local use with your own accounts — it does not proxy or share third-party credentials between users. Provided "as is" under the MIT License, without warranty of any kind.
|
|
314
|
+
|
|
315
|
+
## License
|
|
316
|
+
|
|
317
|
+
[MIT](LICENSE)
|