A local TypeScript task gateway for small-model routing, structured extraction, compression and quality-gated delegation. MIT licensed; early source release, version 0.1.0.
Start tasks in shadow mode, compare local results with the calling assistant, and promote a task category only after enough reviewed evidence. Grunt never calls a paid cloud API itself. When it returns use: big, the calling assistant decides what to do next.
Local Grunt Adapter is a separate Python MCP adapter for Ollama, with file-based input and private-result artifacts. Crest is a separate coding desktop app. Grunt Mode can run independently of either.
This source snapshot comes from OneWave's Grunt development work, with release hardening and portable local configuration. Private Git history, task logs, client data and model weights are excluded.
Requires Node.js 22.13+ with node:sqlite (Node 24 recommended for this release), npm, and a separately installed local llama.cpp-compatible model server. No model/runtime binary is bundled.
git clone https://github.com/OneWave-AI/grunt-mode.git
cd grunt-mode
npm ci --ignore-scripts
npm run build
npm run initInitialization creates private random keys in ~/.config/grunt without printing their values. Set GRUNT_CONFIG_DIR to choose another private configuration folder. Existing keys are preserved. The HTTP token and the backend model key are separate.
Start your model server on loopback with the generated backend key file, for example with a compatible llama.cpp build:
llama-server -m /absolute/path/to/model.gguf --host 127.0.0.1 --port 8091 \
--api-key-file "$HOME/.config/grunt/llm-api-key"Check your exact runtime's flags and model license. Then start the gateway using the model name/alias accepted by that local server:
GRUNT_MODEL=your-local-model GRUNT_LLM_URL=http://127.0.0.1:8091 npm startThe launcher reads private keys locally, defaults to a single model for all tiers, and starts HTTP on 127.0.0.1:8093. It does not start, download or switch models. Direct npm run serve requires a random GRUNT_HTTP_TOKEN of at least 32 characters and the appropriate backend configuration. Never paste tokens into chat.
A separate optional local embedding server enables semantic caching; otherwise those lookups fail closed to ordinary inference. Set GRUNT_EMBED_URL to its loopback endpoint. Confidential tasks bypass both exact and semantic caches.
For CLI use, set backend/key/model environment variables as appropriate and pipe synthetic text:
printf '%s' 'Build failed: src/add.ts has a type error.' | \
node dist/src/cli.js run --task log_ci_summary --caller example --confidential
node dist/src/cli.js statusThe CLI defaults to shadow mode, so a result may say use: big and include a local candidate for comparison. The code returns that result to its caller; it does not contact a cloud service.
For stdio MCP, configure a local client to launch node with the absolute path to dist/src/mcp.js, supplying your local backend configuration and a caller tag in GRUNT_CALLER. Tools are grunt_run, grunt_feedback, grunt_status and grunt_roi. This is a minimal legacy MCP implementation, not a claim of compatibility with every protocol version or hosted client.
Every HTTP endpoint requires Authorization: Bearer <your local HTTP token>. Browser Origin headers are rejected; no CORS access is granted. Use a native local client.
| Endpoint | Purpose |
|---|---|
GET /health |
Local gateway and backend configuration |
GET /status, GET /stats |
Per-task mode and reviewed agreement |
GET /roi?since=YYYY-MM-DD |
Modeled usage by caller/task |
POST /run |
{task, input, caller?, source?, confidential?, schema?} |
POST /feedback |
{id, bigOutput, verdict?, reason?} |
GET /v1/models, POST /v1/chat/completions |
Limited OpenAI-style interface using grunt/<task> names |
The API rejects non-JSON POSTs, foreign Host headers and bodies over the configured cap. Requests are serialized. Authenticated clients are trusted: this is a personal service, not a multi-tenant platform. Do not expose it through public tunnels.
Task modes are shadow, local and off. Promotion to local requires at least 50 shadow examples and 95% agreement. Local mode spot-checks 5% of results, and poor rolling agreement can demote a category. Promotion is an explicit CLI action:
node dist/src/cli.js mode log_ci_summary localThe gate refuses promotion without enough reviewed evidence. Schema checks establish structure, not truth. Self-verification and agreement do not prove correctness; retain caller review for consequential work. The marine-specific task hooks remain disabled and are not safety advice.
confidential suppresses persisted task/feedback content and bypasses exact and semantic result caches. Customer task types and sources such as email/CRM are confidential by default; mark other private work explicitly. exclude suppresses task logging entirely.
Confidential does not hide answers from the calling assistant. CLI, HTTP and MCP responses can contain local answers or candidates; if a cloud assistant receives them, its data policies apply. For private file processing with local-only output artifacts, use the separate Local Grunt Adapter with sensitive=true. Neither project intercepts all prompts in other apps.
Non-confidential records can persist prompts, inputs, outputs and feedback in ~/.local/share/grunt/logs. Heuristic redaction can miss private information. Logs are private by permissions but are retained until manually removed; stop clients before removing them. Cache files also contain derived content. Do not share logs or include them in bug reports.
Backend URLs are limited to HTTP loopback, and model/embedding requests reject redirects. The service does not execute generated shell commands or edit project files. Local clients, the model runtime and other processes under the same OS account are trusted; this is not an OS sandbox.
ops/ preserves the experimental Linux supervisor and signed model-switching helpers. They depend on Linux utilities, Bash 4+, explicit runtime/model paths and local keys. They are not invoked by the quick start and have not been live-tested on this Mac. Inspect and configure them before use. Opt-in supervisor tests require a separate Linux/model environment.
npm test
npm run typecheck
npm auditDefault tests use synthetic inputs and mocked local backends; live-model and Linux-supervisor tests are opt-in. See release review. No model weights are included, and no accuracy or savings benchmark is claimed by this release.
ROI fields such as tokensSaved are estimates based on input size and routing. They omit costs such as orchestration, output and review, and are not measured subscription savings. Dollar fields use caller-supplied prices. Interpret them as exploratory estimates.