greedy-token
Русская версия: README-RU.md
You work in Cursor — greedy-token sits next to the agent (CLI + MCP) so everyday tasks don’t always open a full agent chat.
It routes each task to the cheapest matching tier (tool → python → ollama → rag → cursor; walk TIER_ORDER, best pattern score per tier). Pipeline chains multiple tiers in one call. Escalation to Cursor agent chat only when no cheaper route matches. Each response includes a Greedy token footer vs a naive full-context chat.
Automated tests dashboard — live metrics + Allure 3 preview
Badges and dashboard PNG update after each CI run on
main(Playwright screenshot of the Allure 3 dashboard).
| Link | Description |
|---|---|
| Dashboard | MCP/CLI pytest + contract tests |
| Awesome | Drill-down by epic |
| CI workflow | pytest + gh-pages publish |
In Cursor: your task → greedy-token (MCP/CLI)
↓
route (one tier per task):
tool → python → ollama → rag → cursor
walk TIER_ORDER; best pattern score per tier; ollama tier skipped if server down
↓
pipeline (optional, multi-step):
e.g. check-meta-sync then audit-skill …
composes tool / python / ollama / rag steps — not a separate tier
↓
escalation: Cursor agent chat when no cheaper route matches
What it does
| Layer | When | LLM cost |
|---|---|---|
| tool (rg) | find / grep / search | ~0 |
| python | scripts, meta-sync, gen-env | ~0 |
| ollama | bulk classify, skill audit | cheap LLM |
| rag | lookup in docs/rag/ |
small read |
| cursor | wiring, refactor, architecture | expensive LLM |
Cheap vs expensive LLM
Greedy-token uses cheap and expensive in footers and docs. It is about where token budget goes.
| Label | What it means | Examples |
|---|---|---|
| Cheap LLM | Inference on your runtime (config cheap_llm); tier id ollama in routes; 0 Cursor/API meter on that step |
Ollama (native or remote OLLAMA_URL), LM Studio, llama.cpp, vLLM, TGI — anything via cheap_llm.provider: ollama | openai_compat |
| Expensive LLM | Full agent chat with rules, skills, overhead, and reply — what you pay Cursor (or similar) for | Cursor agent / Composer today; same bucket for Claude, GPT, Copilot when used as the main coding agent or future expensive_llm metered API |
Free tier (tool, python, rag) = no LLM inference at all — ripgrep, scripts, reading docs/rag/ chunks.
Tier order: TIER_ORDER in router.py / routes.yaml — walk tool → python → ollama → rag → cursor; within each tier the highest-scoring pattern wins (ties: first route in config). Not every tier runs on every task. The cheap LLM tier is skipped when the configured runtime is unreachable.
Scope & roadmap
Today the happy path is Cursor + Ollama + workspace. CLI and MCP are IDE-agnostic. v0.6.0 — crystallize L2: script_override telemetry + CLI override, scripts lint, shadow routes, local hub (hub serve), budget policy / llm invoke. v0.5.8 — minimal code search: one greedy_token_search per find task; MCP tool docstrings and cursor rule template forbid route/usage alongside search. v0.5.7 — version SSOT from pyproject.toml (no hardcoded __init__ pin), ./scripts/release-gate.sh TARGET, auto-sync minTestsCount from pytest collection. v0.5.6 — honest search footer, MCP stdio pipeline execute=true e2e, removed dead SearchResult.spent_tokens. v0.5.5 — PyPI-friendly config --init (no workspace required), cursor --execute refusal, usage telemetry aligned to workspace cheap_llm settings. v0.5.3+ pipeline honesty: multi-word search-rag, dry-run footer (saved=0), RAG via rag_est_tokens (cheap_llm.provider: ollama | openai_compat). Paid agent APIs (expensive_llm) remain opt-in / roadmap.
Full matrix (✅ / ❌ / 🔜) + acceptance criteria + GitHub issues: docs/ROADMAP.md · docs/ROADMAP-RU.md
| Area | ✅ today (v0.6.0) | 🔜 next |
|---|---|---|
| Executors | tool, python, ollama (via cheap_llm), rag |
paid bulk APIs; Crystal IR store |
| Agent host | Cursor MCP + token baseline | Claude Desktop, Continue |
| Config | cheap_llm.provider + OLLAMA_* / ollama: aliases |
silent L3 auto-codegen (deferred) |
Install
Python 3.12+ (CI and PyPI builds use 3.12).
pip install greedy-token
# with Cursor MCP server:
pip install "greedy-token[mcp]"
# editable from this clone:
pip install -e ".[dev,mcp]"
# monorepo hub (sibling ../dev):
# cd ../dev && ./scripts/install.sh
export GREEDY_TOKEN_ROOT=/path/to/workspace # optional; auto-detect when markers exist
Cursor integration (recommended)
Full guide (any workspace / PyPI): docs/cursor-setup.md · docs/cursor-setup-RU.md
Starter kit in this repo (copy into your project):
| Template | Copy to |
|---|---|
examples/cursor/mcp.json |
.cursor/mcp.json |
examples/cursor/rules/greedy-token.mdc |
.cursor/rules/greedy-token.mdc |
pip install "greedy-token[mcp]"
mkdir -p .cursor/rules
# from a greedy-token clone, or paste from the docs:
cp examples/cursor/mcp.json .cursor/mcp.json
cp examples/cursor/rules/greedy-token.mdc .cursor/rules/greedy-token.mdc
Then: Settings → MCP → greedy-token → Enable → Refresh → new Agent chat.
Expected: 5 MCP tools (including greedy_token_pipeline).
MCP tools
| Tool | Purpose |
|---|---|
greedy_token_search |
Ripgrep: query + optional path |
greedy_token_rag |
Search docs/rag/ chunks |
greedy_token_route |
Recommend tier + token footer |
greedy_token_pipeline |
Multi-step chain (search/tool → python → ollama → rag) |
greedy_token_usage |
Aggregate savings from ~/.greedy-token/usage.jsonl |
Footers: route / search / rag / pipeline append the full Greedy token block (This call → Tier alternatives → Saved). usage appends Session totals (not the full single-tool footer). pipeline: list returns the recipe list only — no economy footer.
Pipeline (multi-step)
pipeline: meta-audit configurator-boolean
or:
pipeline: check-meta-sync then audit-skill configurator-boolean
Named recipes (pipeline --list):
| Recipe | Steps | Args |
|---|---|---|
meta-audit |
python → ollama | <skill> |
meta-rag |
python → rag | <query> |
search-rag |
rg → rag | <query> <path> · multi-word query + path= · or query= / path= kwargs |
search-rag reuses query for both steps; path scopes ripgrep only:
pipeline: search-rag baseUrl configurator-option-presets.html
pipeline: search-rag baseUrl path=configurator-option-presets.html
Footer includes per-step savings table:
Per-step savings (if each step were a separate naive Cursor chat):
# step executor ms spent baseline saved billing
1 check-meta-sync python 83 0 9,487 9,487 script
2 audit-skill ollama 2698 2,507 9,499 6,992 cheap LLM
Saved by executor (sum of per-step savings):
python (script) steps=1 spent ~0 saved ~9,487
ollama (cheap LLM) steps=1 spent ~2,507 saved ~6,992
CLI commands
| Command | Purpose |
|---|---|
greedy-token route "…" |
Recommend tier + scoring |
greedy-token estimate "…" |
Token-aware estimate + tier scan |
greedy-token run "…" [--execute] |
Route + dry-run / read-only execute |
greedy-token pipeline "…" [--execute] |
Multi-step pipeline |
greedy-token pipeline --list |
Named pipeline recipes |
greedy-token rag QUERY |
Search docs/rag/ |
greedy-token scripts --list |
Workspace script wrappers |
greedy-token scripts --run ID [--execute] |
Run wrapper |
greedy-token audit-context |
Rules/skills token audit |
greedy-token tokens PATH… |
Count tokens in paths |
greedy-token compress |
Short prompt (stdin; --ollama) |
greedy-token report [--since 7d] |
Usage telemetry aggregate |
greedy-token config [--init] [--export] |
Ollama URL/model settings |
greedy-token-mcp |
Start MCP server (stdio) |
Global: --no-log disables telemetry for one invocation.
Pipeline execute: MCP
greedy_token_pipelineand CLIgreedy-token pipelineare dry-run by default. Passexecute=true(MCP) or--execute(CLI) to run allowlisted steps.
Testing
Requires Python 3.12+ (same as CI). GitHub Actions job tests (all) runs the full suite with Allure 3 quality gate, GitHub Pages report, and optional TestOps upload. Line and branch coverage on src/greedy_token/ must stay at 100% (branch = true, fail_under = 100).
CI ethalon: .github/_ethalon/ (action pins in gha-actions.yaml) → runnable .github/workflows/. Same pattern as workspace tests-java/.github/_ethalon/. Sync: ./scripts/sync-github-workflows.sh; CI runs ./scripts/check-github-workflows-sync.sh before pytest.
# from this clone (after pip install -e ".[dev,mcp]"):
python -m coverage run -m pytest tests/ -v --alluredir=build/allure-results
python -m coverage report --include='src/greedy_token/*'
npx --yes allure@3.13.0 quality-gate build/allure-results --config allurerc.mjs
npx --yes allure@3.13.0 generate build/allure-results --config allurerc.mjs -o build/allure-report
# monorepo hub alternative: cd ../dev && ./scripts/install.sh && source .venv/bin/activate && cd ../greedy-token
Coverage: branch = true and fail_under = 100 on src/greedy_token/ (see [tool.coverage.run] / [tool.coverage.report] in pyproject.toml). CI runs coverage run + coverage report on every push/PR.
Layer slices: module → tests/pyramid_layers.py → Allure label layer + pytest marker (-m unit|component|integration|e2e). CI matrix job tests runs each slice separately.
Optional integration tests (real workspace files) run when the checkout includes stacks/java-spring/; set GREEDY_TOKEN_ROOT to override the workspace root.
TestOps: project 5276 on allure.autotests.cloud. CI uploads when repo secret ALLURE_TOKEN is set (ALLURE_PROJECT_ID defaults to 5276, override via repo variable). Pyramid layers (unit / component / integration) are set via Allure label layer in tests/pyramid_layers.py — same keys as Java @Layer and TestOps mappings. Human-readable names use @allure.title / @allure.feature / @allure.story / @allure.epic on each test, and @allure.parent_suite / @allure.suite on each module (pytestmark) for TestOps folder names — JUnit @DisplayName / @Feature equivalent.
Examples
# Search (0 LLM tokens)
greedy-token run "find baseUrl in configurator-option-presets.html" --execute
# RAG lookup
greedy-token rag "baseUrl -D flag"
# Ollama tier
greedy-token route "audit skill configurator-boolean"
# Pipeline dry-run
greedy-token pipeline "pipeline: meta-audit configurator-boolean"
# Pipeline execute (python + ollama)
greedy-token pipeline "check-meta-sync then audit-skill configurator-boolean" --execute
# Savings report
greedy-token report --since 7d
Greedy token footer
route / search / rag / pipeline responses include:
- This call — executor, spent, billing (cheap vs expensive LLM)
- Cursor baseline — rules + task + overhead
- Tier alternatives — selected row matches Spent for this call
- Saved vs naive Cursor chat
Exceptions: usage → Session totals; pipeline: list → recipes only (no economy footer).
Pipeline adds per-step baseline / spent / saved and saved by executor (search bills as rg).
Note: MCP executor steps use cheap/free tiers. Agent chat wrapper (rules + your message + reply) still uses expensive LLM (Cursor tokens).
Usage telemetry
Log file: ~/.greedy-token/usage.jsonl (disable: GREEDY_TOKEN_LOG=0).
Each event: tier, est_tokens, cursor_baseline, cursor_saved, duration_ms.
Pipeline logs one event per step. When the log exceeds GREEDY_TOKEN_LOG_MAX_BYTES (default 5 MiB), it rotates to usage.jsonl.1, .2, …; report reads the active log and archives.
Environment
| Var | Default |
|---|---|
GREEDY_TOKEN_ROOT |
auto-detect or required |
CHEAP_LLM_PROVIDER |
from config or ollama (ollama | openai_compat) |
CHEAP_LLM_URL / OLLAMA_URL |
from config or http://localhost:11434 |
CHEAP_LLM_MODEL / OLLAMA_MODEL |
from config or qwen2.5-coder:7b-instruct-q4_K_M |
GREEDY_TOKEN_LOG |
~/.greedy-token/usage.jsonl |
GREEDY_TOKEN_LOG_MAX_BYTES |
5242880 (5 MiB) |
GREEDY_TOKEN_LOG_MAX_FILES |
5 rotated archives |
Cheap LLM config
Priority (low → high): defaults → ~/.greedy-token/config.yaml → $GREEDY_TOKEN_ROOT/.greedy-token.yaml → CHEAP_LLM_* / OLLAMA_* env (OLLAMA_* = url/model aliases). Route tier id remains ollama.
greedy-token config --init
greedy-token config --init --provider openai_compat --url http://localhost:1234 --model local-model
greedy-token config
eval "$(greedy-token config --export)"
# ~/.greedy-token/config.yaml
cheap_llm:
provider: ollama # or openai_compat
url: http://localhost:11434
model: qwen2.5-coder:7b-instruct-q4_K_M
Routing config
| File | Purpose |
|---|---|
src/greedy_token/config/routes.yaml |
Task routing patterns |
src/greedy_token/config/pipelines.yaml |
Named pipeline recipes |
--execute safety
Auto-execute (read-only or stdout-only): rg, jq, check-meta-sync, pipeline steps in allowlist.
Rsync / migrate / batch-inventory — dry-run only unless run manually.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file greedy_token-0.6.0.tar.gz.
File metadata
- Download URL: greedy_token-0.6.0.tar.gz
- Upload date:
- Size: 887.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab229a531dc82d8d4cc20e90bd7e822f937ae811bcbd364fffac03bf73d79905
|
|
| MD5 |
2967a83d25c57fd46684b608e7b14134
|
|
| BLAKE2b-256 |
9ea62aa569dca829be86027cca9e1fe82b56f038d7d680be7eeb667a0a00ac42
|
Provenance
The following attestation bundles were made for greedy_token-0.6.0.tar.gz:
Publisher:
publish.yml on svasenkov/greedy-token
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
greedy_token-0.6.0.tar.gz -
Subject digest:
ab229a531dc82d8d4cc20e90bd7e822f937ae811bcbd364fffac03bf73d79905 - Sigstore transparency entry: 2172693968
- Sigstore integration time:
-
Permalink:
svasenkov/greedy-token@ebe70b0be53503a2474356aa045699b795e1b463 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/svasenkov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ebe70b0be53503a2474356aa045699b795e1b463 -
Trigger Event:
release
-
Statement type:
File details
Details for the file greedy_token-0.6.0-py3-none-any.whl.
File metadata
- Download URL: greedy_token-0.6.0-py3-none-any.whl
- Upload date:
- Size: 396.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
823096713841ae866e229082968734a668726253f640383fcf8113b709d8cba3
|
|
| MD5 |
07ca1febc5f02cdad22efc024603d4f1
|
|
| BLAKE2b-256 |
fa3a3d5d24b4d79cd3db3880d92ea590d1ea599656e2611e79a8afddf34877bc
|
Provenance
The following attestation bundles were made for greedy_token-0.6.0-py3-none-any.whl:
Publisher:
publish.yml on svasenkov/greedy-token
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
greedy_token-0.6.0-py3-none-any.whl -
Subject digest:
823096713841ae866e229082968734a668726253f640383fcf8113b709d8cba3 - Sigstore transparency entry: 2172693982
- Sigstore integration time:
-
Permalink:
svasenkov/greedy-token@ebe70b0be53503a2474356aa045699b795e1b463 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/svasenkov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ebe70b0be53503a2474356aa045699b795e1b463 -
Trigger Event:
release
-
Statement type: