pedalpoint
Route mechanical development tasks to a local LLM (MLX on Apple Silicon, or Ollama) via Claude Code, so your Claude session goes further. Automatically falls back to local-only mode when Claude quota is exhausted.
What it does
- Hybrid routing: Claude classifies each task. Mechanical work (scaffolding, CRUD, test stubs) goes to your local LLM. Judgment work (architecture, debugging, integration) stays with Claude.
- Three-tier quota fallback: When Claude Pro returns a quota error, pedalpoint first routes judgment and structural tasks to Claude API (pay-per-token) while mechanical tasks continue on local LLM. If the API key is absent or Claude API quota is also exhausted, all tasks fall back to local LLM. Restores to normal when quota recovers.
- Context Courier: Before sending any task to the local LLM, pedalpoint greps your codebase for existing patterns and passes those files to the server. Local LLMs only get tasks they have templates for.
- Drafts, not re-typing: The server writes the local model's output straight to
<file>.draft(only inside the current git repo). Claude reads it, fixes what's wrong, and promotes it withmv— it never re-types the code, which is where the token savings come from. - Proof:
pedalpoint statsreports net Claude output tokens saved per model per week, using real token counts from Claude Code transcripts. - Single install: One script installs the MCP server, pulls the default model, and registers the companion skill.
Requirements
- Claude Code
- Python 3.11+
- Apple Silicon: mlx-lm (installed by the script), or
- Elsewhere: Ollama (or any OpenAI-compatible inference server)
Install
curl -fsSL https://raw.githubusercontent.com/EMSwank/pedalpoint/main/install.sh | sh
The backend defaults to mlx on Apple Silicon and ollama elsewhere. To choose explicitly, or use a custom model or endpoint:
curl -fsSL https://raw.githubusercontent.com/EMSwank/pedalpoint/main/install.sh | \
sh -s -- --backend ollama --model llama3 --base-url http://localhost:11434/v1
Existing installs keep working as Ollama. Re-run with --backend mlx to switch.
Restart Claude Code after install.
Note: If installing without the script, use
uv tool install pedalpoint— notpip install -e .. The tool install putspedalpoint-serverin PATH where Claude Code can find it.
Usage
MLX starts itself. The first local_llm call starts mlx_lm.server (that call takes ~10s longer while the model loads) and it stops after 20 minutes with no calls from any Claude Code session, freeing its ~5GB. A server you start by hand is used as-is and never stopped. Set PEDALPOINT_AUTOSTART=0 to always manage it yourself:
mlx_lm.server --model mlx-community/gemma-4-e4b-it-4bit # backend mlx, manual
ollama serve # backend ollama (or open Ollama.app)
Ollama already unloads idle models on its own (OLLAMA_KEEP_ALIVE, default 5 minutes).
Then in any Claude Code session:
/route-tasks
pedalpoint handles routing automatically. No manual flagging needed.
To verify the MCP server connected:
claude mcp get pedalpoint
Should show Status: ✓ Connected. If disconnected, run pedalpoint-server directly to see the error.
Modes
| Mode | Set via | Behavior |
|---|---|---|
hybrid |
default | Claude classifies each task into mechanical or structural (local draft, Claude reviews inline) or judgment (Agent only). Changes under ~30 lines skip the handoff. |
local-only |
PEDALPOINT_MODE=local-only |
All tasks → local LLM (use when quota exhausted preemptively) |
passthrough |
PEDALPOINT_MODE=passthrough |
All tasks → Claude Agent (disables pedalpoint) |
Configuration
| Variable | Default | Description |
|---|---|---|
PEDALPOINT_BACKEND |
saved choice, else mlx on Apple Silicon / ollama elsewhere |
mlx or ollama. If unset but PEDALPOINT_BASE_URL is set, inferred from the URL (port 11434 → ollama). Otherwise read from ~/.pedalpoint/backend, which install.sh writes; re-running the installer keeps it unless you pass --backend. |
PEDALPOINT_BASE_URL |
mlx: http://localhost:8080/v1; ollama: http://localhost:11434/v1 |
OpenAI-compatible endpoint |
PEDALPOINT_MODEL |
mlx: mlx-community/gemma-4-e4b-it-4bit; ollama: gemma4:12b |
Local model. See Choosing a model. |
PEDALPOINT_MODE |
hybrid |
Routing mode |
PEDALPOINT_TIMEOUT |
120 |
Read timeout in seconds |
PEDALPOINT_AUTOSTART |
1 |
MLX only: start mlx_lm.server on the first call when it isn't running. 0 to manage it yourself. |
PEDALPOINT_IDLE_MINUTES |
20 |
MLX only: stop an auto-started server after this many minutes without calls from any session. |
PEDALPOINT_MAX_TOKENS |
8192 |
Max tokens per draft. Sent on every request (mlx_lm.server defaults to 512). Truncated output is rejected, never written. |
PEDALPOINT_INITIAL_FALLBACK_MINUTES |
60 |
Initial circuit-open duration (doubles on each probe failure) |
PEDALPOINT_API_MODEL |
claude-sonnet-4-6 |
Claude model used for API fallback |
ANTHROPIC_API_KEY |
(unset) | Anthropic API key for Claude API fallback tier. Optional — if unset, circuit skips api_fallback and goes directly to open. |
Choosing a model
Measured on a 16GB M4 MacBook Air with normal apps open (four pedalpoint-style coding tasks, two runs):
| Model | Backend | Passed | Speed | Memory | Notes |
|---|---|---|---|---|---|
mlx-community/gemma-4-e4b-it-4bit (default) |
MLX | 4/4 · 4/4 | 25–28 tok/s | ~4–4.5GB | Most reliable |
mlx-community/Qwen3.5-4B-MLX-4bit |
MLX | 3/4 · 3/4 | 29 tok/s | ~3GB | Lighter; consistently fumbles test-writing |
gemma4:12b |
Ollama | 4/4 | 9.5 tok/s | ~7.5GB | Accurate but slow; pushes a 16GB Mac into swap |
Download a different MLX model with uvx --from huggingface_hub hf download <repo>, set PEDALPOINT_MODEL, and restart Claude Code (an auto-started server picks up the new model the next time it starts). pedalpoint stats shows whether a model pays off on your real work.
Measuring savings
pedalpoint stats # last 7 days
pedalpoint stats --days 30
For each model and week: handoffs, average score (1–7, what Claude had to do with the draft), redo rate, local tokens, net Claude output tokens saved, input overhead, and the share of rows estimated rather than measured. Rows flagged NOT PAYING OFF have an average score under 5 or a net saving ≤ 0. Handoffs are logged to ~/.pedalpoint/handoffs.jsonl.
Uninstall
curl -fsSL https://raw.githubusercontent.com/EMSwank/pedalpoint/main/install.sh | sh -s -- --uninstall
Troubleshooting
| Symptom | Fix |
|---|---|
local_llm calls fail with "MLX not reachable" |
Autostart is off or the URL isn't local: mlx_lm.server --model <model> |
| "MLX server did not start" / "exited while starting" | Read ~/.pedalpoint/mlx.log |
| "mlx_lm.server not found" | uv tool install mlx-lm |
local_llm calls fail with "Ollama not reachable" |
ollama serve (or open Ollama.app on macOS) |
local_llm fails with "Model … not found" |
The error includes the download command (hf download … or ollama pull …) |
local_llm fails with "outside the project repo" or "Not in a git repository" |
Start Claude Code from inside the project's git repo |
| Drafts land in the main checkout instead of your worktree | Update the skill (re-run install.sh): it passes worktree so drafts go to the session's current worktree |
| Anything else | pedalpoint doctor |
/route-tasks says local_llm tool not available |
claude mcp get pedalpoint (check status; if missing, re-run install) |
claude_api returns "ANTHROPIC_API_KEY not set" — api_fallback tier disabled |
export ANTHROPIC_API_KEY=sk-ant-... then restart Claude Code |
| All tasks route to local LLM even after Claude quota resets | echo '{"circuit":"closed"}' > ~/.pedalpoint/state.json |
Development
git clone https://github.com/EMSwank/pedalpoint
cd pedalpoint
uv sync --extra dev # or: pip install -e ".[dev]"
pytest tests/unit/ -v
Integration tests (require a running model server):
PEDALPOINT_INTEGRATION=true PEDALPOINT_BACKEND=ollama pytest tests/integration/test_ollama.py -v
PEDALPOINT_INTEGRATION=true PEDALPOINT_BACKEND=mlx pytest tests/integration/test_mlx.py -v
Install script tests (requires bats-core):
brew install bats-core # macOS; use apt-get install bats on Linux
bats tests/install/
License
MIT
Metadata
Release files for pedalpoint 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pedalpoint-0.5.0.tar.gz | 115.0 kB | With provenance | Details for pedalpoint-0.5.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pedalpoint-0.5.0-py3-none-any.whl | Python 3 | none | any | Details for pedalpoint-0.5.0-py3-none-any.whl |
Total release size: 140.9 kB
Release files / pedalpoint-0.5.0.tar.gz
| Download URL | pedalpoint-0.5.0.tar.gz |
|---|---|
| Size | 115.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4b0c5ae2afb8d1a4560f69ecb60689d9a3df51ed3a89bef642c581c6a085ed90
|
|
BLAKE2b-256 checksum How to use checksums |
31f2bdf6dcb585f9679e2eab37e2483d1265452cb8559516f660f4b00fa00f4e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / pedalpoint-0.5.0-py3-none-any.whl
| Download URL | pedalpoint-0.5.0-py3-none-any.whl |
|---|---|
| Size | 25.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b63ee39acf52d10956ce68a31f895ec9227c2d1d1aac7bd9d90c1ef5c545b5ba
|
|
BLAKE2b-256 checksum How to use checksums |
4fc0575d2d5d8f5acff5e08756325d33efbb0944e3cfb394c1c38297b1719ae2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logSecurity for pedalpoint 0.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for pedalpoint-0.5.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.