Ficelle
Ficelle is a standalone local OpenAI-compatible strict-zero model router for agent clients. Codex, Cursor, Continue, Open WebUI, Hermes, and custom scripts all point at the same local endpoint — no host application is required (one recipe per client). Claude Code speaks the Anthropic protocol and cannot point at Ficelle directly yet; its page says what works today. Hermes is one optional, first-class integration among them: where it is installed, it sees Ficelle as one of its LLM providers.
It exposes http://127.0.0.1:8646/v1 with stable virtual models such as ficelle/auto-orchestrator, ficelle/auto-tools, ficelle/auto-json, ficelle/auto-compression, ficelle/auto-long, ficelle/auto-fast, and capability-specific virtual models for coding, reasoning, multimodal, vision, video, and audio routing. ficelle/auto-coding fails closed unless Ficelle has published a current signed certification for the exact provider deployment.
Current status
Ficelle is at v0.3.6: usable for local real-use, installable from a pinned bootstrap or from PyPI, and deliberately conservative about provider costs.
Solid today:
- local OpenAI-compatible
/v1/modelsand/v1/chat/completionsendpoints; - strict-zero default routing: free pricing required, tools required by default, no paid fallback;
- OpenRouter and Nous/RMS provider support;
- NVIDIA NIM, Mistral, Groq, Gemini (Google AI Studio), and Cerebras as credential-gated
free_quotaproviders (enabled but dormant without a key), not strict-zero; - Cavoti as a credential-gated
free_quotarelay (four tier entries —cavoti_basic,cavoti_gpt_premium,cavoti_claude_plus,cavoti_claude_premium, EU/Germany node) that resells paid frontier models (Claude/GPT/DeepSeek/GLM/Grok) under a free Pro quota — a grey-market relay, not a first-party free tier and not strict-zero, dormant without a key. The tiers share one daily dollar pool (shared_accountscope) and carry a per-tierburn_weightso routing prefers the cheapest tier; - SiliconFlow as a credential-gated
free_quotaprovider exposing one genuinely-free model (nex-agi/Nex-N2-Pro, 262K context, tools) through an id allowlist (its catalog ships no pricing) — an independent free quota that aggregates with OpenRouter for the same model; not strict-zero, dormant without a key; - Ollama Cloud as a credential-gated
free_quotaprovider admitting its cloud catalogue without an allowlist, with runtime model-only quarantine when a listed model becomes subscription-only — preview quota, not strict-zero, dormant without a key; - GitHub Models as a
free_quotaintegration that is wired and tested but dormant — not registered in the default config (absent from the UI, routes nothing): its free tier hard-caps request input at 8000/4000 tokens, so no free model reaches the 128k usable-input floor; the definition (GITHUB_MODELS_PROVIDER_DEF) stays in the tree, one edit from activation if GitHub raises the cap; - OpenCode Zen as a credential-gated
free_modelprovider exposing only explicit allowlisted FreeModel IDs (deepseek-v4-flash-free,mimo-v2.5-free,nemotron-3-ultra-free,north-mini-code-free), like OpenRouter free models rather than provider-wide FreeQuota, dormant without a key; - Kilo Code (Kilo AI Gateway) as a credential-gated
free_modelprovider on a non-standard path (/api/gateway, no/v1); the free pool requires both the provider'sisFree=truemarker and strict-zero catalog pricing, with no allowlist to maintain (provider_free_catalog_pricingproof — disagreements, paid, and sparse rows fail closed); never strict-zero, dormant without a key; - Cohere (OpenAI Compatibility API) as a credential-gated
free_quotaprovider (dormant without a key) exposing the Command chat models that support tools and ≥128K context (its/v1/modelsships no pricing/context, so a per-provider id allowlist scopes the free pool, like SiliconFlow); not strict-zero; - Naraya / NaraRouter (OpenAI-compatible gateway) as a credential-gated
free_quotaprovider (dormant without a key), a third-party reseller router whose sparse/v1/modelsships no pricing, so a mandatory id allowlist (require_model_id_allowlist, fail-closed) scopes the free pool to five fast open-weight chat models (the resold Claude/GPT/Gemini are excluded as unusably throttled);free_scope: provider(one 5M-tokens/day quota); not strict-zero; - OrcaRouter (
free_model) as a credential-gated official free-id pool: every catalog id ending in-free, plusorcarouter/free. Paid Claude/GPT rows and sparse fusion aliases stay out; no hand-maintained allowlist. Hetzner Inference is registered as credential-gatedfree_quota; Ficelle follows its definitive authenticated catalog without a hard-coded model list, while capability and context filters still fail closed; - macOS LaunchAgent and Linux
systemd --userlifecycle through theficelleCLI; - conservative setup wrapper through
scripts/install-ficelle.pyandficelle-setup; - Hermes provider plugin template for the
ficelleprovider; - admin UI and machine-readable
/admin/status.json; - request routing logs, last-route state, provider/model errors, cooldowns, quarantine, benchmarks, canaries, audit log, and virtual model rollback;
- per-request token accounting with a windowed savings estimate on the admin Requests page (
Spent $0.00under strict-zero,Est. savedat the routed models' own paid-sibling rates, recorded at catalog refresh); - default-off native context compression controls with dry-run reporting, local CCR retrieval, admin observability, and live-zone limited to low-risk real-use pending evidence.
Deliberately not done yet:
- no paid fallback;
- no quota-based providers enabled by default;
- no native macOS app before the CLI/package path is stable.
Architecture at a glance
OpenAI-compatible client / optional Hermes integration
|
v
http://127.0.0.1:8646/v1
|
v
Ficelle router
|- config + virtual profiles
|- strict-zero catalog filtering
|- provider credential resolution
|- model scoring and fallback
|- cooldowns / quarantine / failure classification
|- benchmarks / canaries / verified capability state
`- admin API + dashboard + logs
|
v
OpenRouter / Nous / future gated providers
Runtime state lives under ~/.ficelle/ by default, independently of any client integration. Provider secrets are resolved from the environment / Ficelle keychain (~/.ficelle/ficelle-secrets.keychain-db on macOS) and must never be committed.
Repository layout
.
├── AGENTS.md # operating rules for autonomous coding agents
├── CLAUDE.md # Claude Code entrypoint, points to AGENTS.md
├── README.md # this overview
├── config.example.json # safe example runtime config
├── ficelle_router.py # legacy compatibility entrypoint
├── scripts/install-ficelle.py # source-checkout setup wrapper
├── scripts/compression-dogfood-report.py # local compression real-use metrics
├── src/ficelle/
│ ├── cli.py # ficelle CLI and LaunchAgent lifecycle
│ ├── install.py # ficelle-setup package installer
│ ├── router.py # HTTP router, admin UI/API, selection engine
│ ├── service.py # platform service backend abstraction
│ └── assets/hermes-plugin/ # packaged Hermes plugins
├── plugins/ficelle-compression/ # source Hermes retrieval tool plugin
├── plugins/model-providers/ficelle/ # source Hermes provider plugin template
├── skills/ficelle-router/ # Hermes skill for operating Ficelle
├── tests/ # pytest regression suite
└── docs/ # product, architecture, PRDs, runbooks
Install for local development
cd ~/Projets/ficelle
python -m pip install -e '.[dev]'
Run local checks:
python -m pytest -q
python -m compileall src ficelle_router.py
Standalone setup
Ficelle needs Python 3.11+, but it does not require Hermes. The open Core is
published as ficelle-router:
uv tool install ficelle-router # or: pip install ficelle-router
ficelle-setup --skip-package --target generic
Run interactively, setup ends by offering to paste your OpenRouter key (hidden input;
routing uses your own key — nothing serves without one) and then runs ficelle demo,
so the first routed completion happens inside the install session. Scripted or
declined, the equivalent manual steps are:
ficelle set-key openrouter # or pipe it: ficelle set-key openrouter --stdin
ficelle doctor --text
ficelle health
ficelle models
For end users the pinned bootstrap in docs/install.md stays
the recommended path: it is the only one that verifies the wheel it installs
against a SHA-256 pinned in the script. An authorized source checkout also works:
git clone https://github.com/TheBlueHouse75/ficelle.git
cd ficelle
python scripts/install-ficelle.py --target generic
Then point any OpenAI-compatible client at http://127.0.0.1:8646/v1:
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:8646/v1",
api_key="ficelle-local",
)
The public bootstrap installs the private Ficelle Pro wheel when a licence key is present:
(
read -s FICELLE_LICENSE_KEY
export FICELLE_LICENSE_KEY
curl -fsSL https://raw.githubusercontent.com/TheBlueHouse75/ficelle-open-core/v0.3.6/scripts/bootstrap-ficelle.py | python3 - --target generic
)
That command does not require cloning this repo and keeps the key out of argv and shell history. The bootstrap downloads the private wheel, selects a target, installs into a target-aware Python, and runs the packaged setup flow. --target auto is the default: it uses the Hermes integration when a reliable local Hermes signal is found, and otherwise installs the generic standalone target. Use --target generic or --target hermes to make the launch target explicit.
Dry-run first when validating a new environment:
python scripts/install-ficelle.py --dry-run
python scripts/bootstrap-ficelle.py \
--wheel-url ficelle-pro/dist/ficelle_pro-0.3.6-py3-none-any.whl \
--target generic \
--dry-run
After package installation, the same setup flow is available as:
ficelle-setup --skip-package --target generic
The setup wrapper starts with readable preflight checks, installs the package when requested, starts the selected local service backend, and runs doctor, health, and models smoke checks. It always passes FICELLE_HOME (default ~/.ficelle) to the service; generic and OpenClaw targets do not inherit or create HERMES_HOME.
For a safer first pass on a new machine:
python scripts/install-ficelle.py --preflight-only
python scripts/install-ficelle.py --dry-run --target generic
Only the Hermes target installs the packaged provider/tool plugins. Hermes config remains opt-in: --target hermes --configure-hermes writes a ready snippet to ~/.hermes/ficelle/hermes-config.snippet.yaml, creates ~/.hermes/config.yaml only when absent, or updates an existing Ficelle-managed block with a timestamped backup. Existing unmanaged configs are left untouched. ficelle-setup --target hermes --rollback restores the latest available integration backups; paths without a backup are always left untouched.
When upgrading from the former layout, setup implicitly copies ~/.hermes/ficelle/ to ~/.ficelle/ only when no Ficelle home was explicitly selected and the destination is absent, empty, or contains only credential files. Existing credentials and the legacy source are preserved; a destination containing runtime data is left untouched.
Today, the managed service backends are macOS LaunchAgent, Linux systemd --user, and a Windows per-user Scheduled Task (no elevation required; provider secrets resolve through the Windows Credential Manager). The Windows and Linux backends still need clean-host validation before public release claims.
See docs/install.md for source, wheel, dry-run, Hermes config, and verification details.
CLI commands
ficelle install
ficelle start
ficelle stop
ficelle restart
ficelle status
ficelle refresh
ficelle health
ficelle models
ficelle doctor --json
ficelle canary
ficelle synthetic-health run --depth deep --json
ficelle export
synthetic-health is the deep, sequential user-view health harness for weekly reference-installation
runs. It exercises every configured virtual profile and every invokable strict-zero model through
the loopback API, then correlates responses with route logs and state. Scheduling is disabled until
explicitly installed. See docs/components/synthetic-health.md.
Useful local endpoints:
curl -s http://127.0.0.1:8646/health
curl -s http://127.0.0.1:8646/admin/status.json | python -m json.tool
curl -s http://127.0.0.1:8646/v1/models | python -m json.tool
Optional Hermes integration
Hermes is not required to run Ficelle. With --target auto, setup selects Hermes only when it detects a Hermes Python/runtime, CLI, config, or agent directory. --target hermes selects it explicitly, installs the Ficelle provider and compression plugins with idempotent backups, and passes HERMES_HOME only to that integration. The provider name is ficelle, with display label Ficelle FREE.
Export the recommended Hermes YAML:
ficelle export --target hermes
Setup makes Ficelle the main Hermes route through ficelle/auto-orchestrator and also installs
specialized auxiliary slots:
model:
provider: "custom"
base_url: "http://127.0.0.1:8646/v1"
model: "ficelle/auto-orchestrator"
auxiliary:
title_generation:
provider: "ficelle"
model: "ficelle/auto-fast"
compression:
provider: "ficelle"
model: "ficelle/auto-compression"
web_extract:
provider: "ficelle"
model: "ficelle/auto-json"
ficelle/auto-compression is the Hermes compaction slot. ficelle/auto-long means large-context routing and is intentionally not the default compression recommendation.
Experimental OpenClaw integration
ficelle-setup --target openclaw installs the standalone service without Hermes files or environment. OpenClaw integration is experimental: review and merge the export from /admin/export/openclaw manually.
Documentation
Start with docs/README.md.
Key docs:
docs/install.md— source/wheel setup and verification.docs/components/router.md— routing engine, provider policy, fallback, state.docs/components/cli-and-service.md— CLI, setup wrapper, service lifecycle.docs/components/service-backends.md— service backend abstraction, macOS LaunchAgent, Linux systemd user service, unsupported platforms.docs/components/hermes-integration.md— provider plugin and Hermes config.docs/components/admin-and-observability.md— admin UI/API, status, logs, audit, dashboard.docs/components/config-and-state.md— config and runtime state files.docs/testing-and-verification.md— local checks, live smokes, release validation.docs/features-next-steps.md— current tracking file and remaining work.docs/ficelle-prd.md— umbrella product PRD.docs/prds/README.md— focused PRD index.
Provider policy
Enabled by default (strict-zero catalog):
- OpenRouter;
- Nous/RMS.
Enabled but credential-gated free_quota (dormant without a key, never strict-zero):
- NVIDIA NIM;
- Mistral. Unlike NVIDIA NIM, Mistral bills the same model IDs if the account carries a billing budget, so keep the account on the Experiment plan with no budget; the anti-false-free guard quarantines any model the runtime reports as billed.
- Groq. Same posture as Mistral: bills the same model IDs if the account carries a billing budget, so keep the account on the free tier with no budget; its free tier is rate-limited (~30 RPM), so expect more rate-limit cooldowns.
- Gemini (Google AI Studio). Same billing posture (free tier, no budget) and a tighter rate limit (~15 RPM, 1500 RPD on Flash). Off unless
GEMINI_API_KEYis configured. - SiliconFlow. An OpenAI-compatible aggregator whose
/v1/modelsships no pricing, so a per-provider id allowlist restricts the free pool to the one genuinely-free model (nex-agi/Nex-N2-Pro, 262K context, tools). An independent free quota that aggregates with OpenRouter's copy of the same model. Keep the account with no paid top-up; the anti-false-free guard quarantines any model the runtime reports as billed. Off unlessSILICONFLOW_API_KEYis configured. - Ollama Cloud. An OpenAI-compatible endpoint (
https://ollama.com/v1, not/api/v1) whose/v1/modelsis admitted as the cloud free-quota catalogue (free_scope: provider, no allowlist). A listed model can later require a subscription: HTTP 403requires a subscription/upgrade for accessquarantines only that model, raises a Control Center notice, and does not pause the rest of Ollama. The account-wide preview quota remains unpublished and unstable, and Ollama meters it by GPU time, not tokens — generic quota cooldown/probe recovery handles exhaustion. Open point: commercial use of the free tier is not confirmed in Ollama's ToS. Off unlessOLLAMA_API_KEYis configured. - Cohere (OpenAI Compatibility API). Its Compatibility
/v1/modelsis OpenAI-shaped but sparse (no pricing or context) and mixes chat models with embeddings, rerank, transcribe, and vision, so a per-provider id allowlist restricts the free pool to the Command chat models that support tools and ≥128K context (command-a-03-2025,command-a-plus-05-2026,command-a-reasoning-08-2025,command-r-08-2024,command-r-plus-08-2024,command-r7b-12-2024,command-r7b-arabic-02-2025,north-mini-code-1-0; verified live 2026-06-21). Keep the account with no paid budget; the anti-false-free guard quarantines any model the runtime reports as billed. The free tier is rate-limited (~20 RPM, ~1000 calls/month), so expect more rate-limit cooldowns. Off unlessCOHERE_API_KEY(orCO_API_KEY) is configured. - Naraya / NaraRouter (OpenAI-compatible gateway,
https://router.naraya.ai/v1). A third-party reseller router (like OpenRouter) that resells premium models at low IDR prices; its/v1/modelsis sparse with no pricing, so a mandatory per-provider id allowlist (require_model_id_allowlist, fail-closed) restricts the free pool to five open-weight chat models confirmed live 2026-06-21 to answer fast (1-5s) with tools and ≥252K context (mistral-large,mistral-medium-3-5,minimax-m3,deepseek-v4-flash-naraya,qwen3.7-max-naraya). The resold premium models (Claude/GPT/Gemini) are excluded: live they were throttled to a 22-43s time-to-first-byte, unusable for an agent. One 5M-tokens/day quota is shared account-wide (free_scope: provider), and no quota headers are exposed (consumption is visible only on the Naraya dashboard). Create the key with no credit card so the free pool cannot spill into paid pay-as-you-go. Off unlessNARAYA_API_KEYis configured.
Enabled but credential-gated free_model (dormant without a key, model allowlist only):
- OpenCode Zen. An OpenAI-compatible gateway whose
/zen/v1/modelscatalog is sparse and whose Free models are model-specific, not provider-wide quota. Ficelle routes only explicit allowlist entries:deepseek-v4-flash-free,mimo-v2.5-free,nemotron-3-ultra-free, andnorth-mini-code-freeafter a live smoke on 2026-06-20. Ended free promotions are quarantined model-scoped. Off unlessOPENCODE_ZEN_API_KEYis configured. - Kilo Code (Kilo AI Gateway). An OpenAI-compatible aggregator on a non-standard path (
/api/gateway/chat/completions, no/v1). Its rich catalog exposes per-model pricing and anisFreeflag, so Ficelle requires both signals to agree:isFree=trueand strict-zero prompt/completion pricing. There is no allowlist to maintain; a newly-added model routes with no code change only when both provider signals agree and the normal tools/context gates pass. Rows marked paid, sparse-pricing rows, and contradictions such asisFree=falsewith$0pricing fail closed. The dedicatedprovider_free_catalog_pricingproof keeps the provider FreeModel (a credential-gated opt-in outside the default strict-zero pool) while retaining strict-zero pricing evidence. Paid or billable routes returnHTTP 402at zero balance and are quarantined model-scoped; keep the account at 0 credits so paid/flipped models fail closed. Off unlessKILO_API_KEYis configured. Reverified 2026-08-21 afterstealth/ox-alphaexposed$0pricing withisFree=falseand returned 402 while anisFree=truecontrol route succeeded; the:freemodels' commercial-use rights are unconfirmed.
Wired but not registered (dormant, absent from the admin UI, routes nothing):
- GitHub Models. The integration is complete and tested but is deliberately not registered in the default config, because its free tier hard-caps request input at 8000 tokens (low/high tier) or 4000 (custom tier) and 403s the top reasoning models (o1/o3) — verified live 2026-06-21 — so no free model reaches the 128k usable-input floor, even though its non-standard
/catalog/modelsreports each model's much larger native window. The provider definition (GITHUB_MODELS_PROVIDER_DEF) and its support code (non-standard catalog fetcher, credential path, tests) stay in the tree so it is one edit away from activation if GitHub raises the cap. Tools are confirmed working; auth would be a GitHub PAT scopedmodels:read(GITHUB_MODELS_API_KEY; the ambientGITHUB_TOKENis intentionally not auto-resolved).
Rules:
- default routing must never create silent spend;
allow_paid_fallbackstaysfalseunless explicitly changed and documented;- provider keys stay in the environment / Ficelle keychain, never repo files;
- auth diagnostics are presence-only and redacted;
- catalog claims must be separated from benchmark/canary-verified capability state.
Security
- No secrets in this repository.
- No provider keys in config, state fixtures, docs, screenshots, or logs committed to git.
- Runtime state lives under
~/.ficelle/, outside the repo. - Route logs should contain request IDs, selected models, statuses, reasons, latency, and redacted details, not prompts or credentials.
- Admin surfaces are local-only for the MVP.
Development workflow
Read AGENTS.md before changing code. The short version:
- Inspect existing code and docs before editing.
- Keep the diff minimal.
- Update docs with behavior changes.
- Run relevant tests/checks.
- Verify
git diff --checkandgit statusbefore handing off. - Do not push without explicit approval.
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 ficelle_router-0.3.6.tar.gz.
File metadata
- Download URL: ficelle_router-0.3.6.tar.gz
- Upload date:
- Size: 679.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69491c476eead607776271a5baa9baafb5aa611e310946a75b48a908bc4b7e06
|
|
| MD5 |
26ffa34459d206ac76391d288988337f
|
|
| BLAKE2b-256 |
c4839bebdc1e21cc372bd4b70641c2df33b52e0d58fea6aa485c0a1e88a062c6
|
Provenance
The following attestation bundles were made for ficelle_router-0.3.6.tar.gz:
Publisher:
publish-pypi.yml on TheBlueHouse75/ficelle-open-core
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ficelle_router-0.3.6.tar.gz -
Subject digest:
69491c476eead607776271a5baa9baafb5aa611e310946a75b48a908bc4b7e06 - Sigstore transparency entry: 2554798549
- Sigstore integration time:
-
Permalink:
TheBlueHouse75/ficelle-open-core@a559f3a2dfe0ccde9ea653cab476a5cad530dc4e -
Branch / Tag:
refs/tags/v0.3.6 - Owner: https://github.com/TheBlueHouse75
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@a559f3a2dfe0ccde9ea653cab476a5cad530dc4e -
Trigger Event:
release
-
Statement type:
File details
Details for the file ficelle_router-0.3.6-py3-none-any.whl.
File metadata
- Download URL: ficelle_router-0.3.6-py3-none-any.whl
- Upload date:
- Size: 689.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b56865cab854371ce3c783370878e2dcea7c5b7f9617c690ee3c6bff3273cf81
|
|
| MD5 |
f3cff8892f563a53956de9f6dbd504f7
|
|
| BLAKE2b-256 |
f4c4df1237dbc2c0e9675d5d14916a44a546a7a4a0bbd92751e7ecdf654621fa
|
Provenance
The following attestation bundles were made for ficelle_router-0.3.6-py3-none-any.whl:
Publisher:
publish-pypi.yml on TheBlueHouse75/ficelle-open-core
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ficelle_router-0.3.6-py3-none-any.whl -
Subject digest:
b56865cab854371ce3c783370878e2dcea7c5b7f9617c690ee3c6bff3273cf81 - Sigstore transparency entry: 2554798583
- Sigstore integration time:
-
Permalink:
TheBlueHouse75/ficelle-open-core@a559f3a2dfe0ccde9ea653cab476a5cad530dc4e -
Branch / Tag:
refs/tags/v0.3.6 - Owner: https://github.com/TheBlueHouse75
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@a559f3a2dfe0ccde9ea653cab476a5cad530dc4e -
Trigger Event:
release
-
Statement type: