1jehuang / 1jehuang/jcode

Feature request: add OmniRoute as a built-in OpenAI-compatible provider profile

Open
#704 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

autonomous: no enhancement from-pr priority: low triage: needs-decision
Dominant language
Rust
Stars
19.9k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
30

Description

Proposal

Add OmniRoute as a built-in OpenAI-compatible provider profile, following the exact same data-driven pattern as the existing openrouter, deepseek, kimi, ollama and lmstudio profiles.

OmniRoute is a free, MIT-licensed, self-hosted AI gateway: one OpenAI-compatible endpoint routing to 290+ providers (90+ free) and 500+ models, with quota-aware auto-fallback, token compression (15–95% savings) and MCP/A2A support. It is already widely used as the local router behind coding agents (Claude Code, Codex, Cursor, OpenCode, Cline, Copilot) — jcode users get all of that through a single jcode login --provider omniroute.

The project is one of the fastest-growing open-source repositories in Brazil right now:

  • 36.6k stars, 4.7k forks, 300+ code contributors — from zero in Feb/2026 to this in ~6 months
  • 🇧🇷 Top-2 among Brazilian software repositories on GitHub, and just reached top-2 monthly (trending)
  • Actively maintained: v3.8.50, weekly releases, 48 CI quality gates

We will also feature jcode in the OmniRoute README — we are adding a new "Tools & repositories that work with OmniRoute" section and jcode will be listed there with a link, exposing jcode to OmniRoute's user base.

Reference implementation

A complete, validated implementation is available in our fork:

PR: https://github.com/diegosouzapw/jcode/pull/1
Branch: diegosouzapw:feat/omniroute-provider (commit ee4f904e6)

The diff is small and focused: 6 files, +56/−3, no new crate, no runtime changes.

Changes
  • crates/jcode-provider-metadata/src/catalog.rs: OMNIROUTE_PROFILE (id omniroute, api base http://localhost:20128/v1, api_key_env OMNIROUTE_API_KEY, requires_api_key: true), added to OPENAI_COMPAT_PROFILES, plus OMNIROUTE_LOGIN_PROVIDER descriptor.
  • src/cli/provider_init.rs: ProviderChoice::OmniRoute (aliases omniroute / omni / omniroute-ai), as_arg_value()"omniroute", login-table entry.
  • src/cli/commands/report_info.rs: provider-list wiring for the new choice.
  • README.md: omniroute added to the built-in profile id list.
  • Tests: alias parse (args/tests.rs), catalog round-trip (provider_init_tests.rs), and env hygiene — the auto no-credentials fixture now clears OMNIROUTE_API_KEY so an ambient key can't leak into the "no credentials" invariant.
Validation
  • cargo check --workspace: clean, 0 errors.
  • jcode lib suite: 205 passed / 1 failed — the single failure (configured_auth_test_targets_only_include_configured_supported_providers) is pre-existing on the base branch (environmental: no provider API keys in the local shell), unrelated to this change.
  • jcode-provider-metadata (14 tests) and jcode-base auth-integration registry tests pass with the 49th login provider.

Notes for the maintainer

Per your CONTRIBUTING.md, feel free to treat this as a reference and rewrite it your way — the catalog entry itself is the essential part; everything else mechanically follows the existing profile pattern. Happy to adjust anything (id, aliases, default base, menu ordering) to your preference.

A git patch is attached below for convenience.


omniroute-provider.patch (click to expand)
From ee4f904e61a8342d9dc67c4cf3e20cdf1d10a9d0 Mon Sep 17 00:00:00 2001
From: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Date: Sat, 1 Aug 2026 09:45:17 -0300
Subject: [PATCH] feat(provider): add OmniRoute OpenAI-compatible provider (id
 omniroute)

Adds OmniRoute, a self-hosted unified AI proxy/router exposing 290+ LLM
providers behind a single OpenAI-compatible endpoint, as a first-class
OpenAI-compatible provider profile. It defaults to the local server base
URL (http://localhost:20128/v1) like Ollama/LM Studio; point it at a
remote deployment and set OMNIROUTE_API_KEY for production.

- OMNIROUTE_PROFILE in the metadata catalog (api_key_env OMNIROUTE_API_KEY)
- ProviderChoice::OmniRoute (aliases omniroute/omni/omniroute-ai) + login descriptor
- README profile-list entry
- Tests: alias parse, catalog round-trip; clear OMNIROUTE_API_KEY in the
  auto no-credentials fixture so the new provider does not leak a key
  from the ambient environment into the "no credentials" invariant.
---
 README.md                                     |  2 +-
 crates/jcode-provider-metadata/src/catalog.rs | 36 +++++++++++++++++--
 src/cli/args/tests.rs                         |  3 ++
 src/cli/commands/report_info.rs               |  1 +
 src/cli/provider_init.rs                      | 11 ++++++
 src/cli/provider_init_tests.rs                |  6 ++++
 6 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 33505db8d..7f9303815 100644
--- a/README.md
+++ b/README.md
@@ -365,7 +365,7 @@ There are two ways to set one up:
   jcode login --provider moonshotai
  • Built-in OpenAI-compatible profile ids include: openrouter, deepseek, zai, kimi, moonshotai, opencode (OpenCode Zen), opencode-go, 302ai, baseten, cortecs, huggingface, nebius, scaleway, stackit, and firmware. Each profile only sets the endpoint and key variable; you still pick the model with /model (or --model). Run jcode login with no provider to see the interactive list.
  • Built-in OpenAI-compatible profile ids include: openrouter, deepseek, zai, kimi, moonshotai, opencode (OpenCode Zen), opencode-go, 302ai, baseten, cortecs, huggingface, nebius, scaleway, stackit, firmware, and omniroute. Each profile only sets the endpoint and key variable; you still pick the model with /model (or --model). Run jcode login with no provider to see the interactive list.
  • Any other endpoint — point jcode at an arbitrary OpenAI-compatible API (hosted or local) with jcode login --provider openai-compatible or the scriptable jcode provider add command described below.

diff --git a/crates/jcode-provider-metadata/src/catalog.rs b/crates/jcode-provider-metadata/src/catalog.rs
index cc30d1a2c..5d2c40b2c 100644
--- a/crates/jcode-provider-metadata/src/catalog.rs
+++ b/crates/jcode-provider-metadata/src/catalog.rs
@@ -421,6 +421,23 @@ pub const CELERIS_PROFILE: OpenAiCompatibleProfile = OpenAiCompatibleProfile {
requires_api_key: true,
};

+// OmniRoute: a self-hosted unified AI proxy/router exposing 290+ LLM providers
+// behind a single OpenAI-compatible endpoint, with auto-fallback and combo
+// routing. It defaults to the local server's base URL (like Ollama/LM Studio);
+// point it at a remote deployment and set OMNIROUTE_API_KEY for production.
+// Like the other aggregator profiles (OpenRouter), there is no single default
+// model — routing/model is chosen at runtime, so the user picks with /model.
+pub const OMNIROUTE_PROFILE: OpenAiCompatibleProfile = OpenAiCompatibleProfile {

  • id: "omniroute",
  • display_name: "OmniRoute",
  • api_base: "http://localhost:20128/v1",
  • api_key_env: "OMNIROUTE_API_KEY",
  • env_file: "omniroute.env",
  • setup_url: "https://github.com/diegosouzapw/OmniRoute",
  • default_model: None,
  • requires_api_key: true,
    +};

pub const OPENAI_COMPAT_PROFILE: OpenAiCompatibleProfile = OpenAiCompatibleProfile {
id: "openai-compatible",
display_name: "OpenAI-compatible",
@@ -432,7 +449,7 @@ pub const OPENAI_COMPAT_PROFILE: OpenAiCompatibleProfile = OpenAiCompatibleProfi
requires_api_key: true,
};

-pub(crate) const OPENAI_COMPAT_PROFILES: [OpenAiCompatibleProfile; 37] = [
+pub(crate) const OPENAI_COMPAT_PROFILES: [OpenAiCompatibleProfile; 38] = [
OPENCODE_PROFILE,
OPENCODE_GO_PROFILE,
ZAI_PROFILE,
@@ -469,6 +486,7 @@ pub(crate) const OPENAI_COMPAT_PROFILES: [OpenAiCompatibleProfile; 37] = [
CELERIS_PROFILE,
LMSTUDIO_PROFILE,
OLLAMA_PROFILE,

  • OMNIROUTE_PROFILE,
    OPENAI_COMPAT_PROFILE,
    ];

@@ -990,6 +1008,19 @@ pub const OLLAMA_LOGIN_PROVIDER: LoginProviderDescriptor = LoginProviderDescript
order: LoginProviderSurfaceOrder::new(Some(35), Some(35), Some(35), Some(35), Some(35)),
};

+pub const OMNIROUTE_LOGIN_PROVIDER: LoginProviderDescriptor = LoginProviderDescriptor {

  • id: "omniroute",
  • display_name: "OmniRoute",
  • auth_kind: LoginProviderAuthKind::ApiKey,
  • auth_state_key: LoginProviderAuthStateKey::OpenRouterLike,
  • auth_status_method: "API key",
  • aliases: &["omni", "omniroute-ai"],
  • menu_detail: "self-hosted OpenAI-compatible router (OmniRoute); localhost by default",
  • recommended: false,
  • target: LoginProviderTarget::OpenAiCompatible(OMNIROUTE_PROFILE),
  • order: LoginProviderSurfaceOrder::new(Some(37), Some(37), Some(37), Some(37), Some(37)),
    +};

pub const OPENAI_COMPAT_LOGIN_PROVIDER: LoginProviderDescriptor = LoginProviderDescriptor {
id: "openai-compatible",
display_name: "OpenAI-compatible",
@@ -1112,7 +1143,7 @@ pub const GOOGLE_LOGIN_PROVIDER: LoginProviderDescriptor = LoginProviderDescript
order: LoginProviderSurfaceOrder::new(Some(13), None, None, None, None),
};

-pub(crate) const LOGIN_PROVIDERS: [LoginProviderDescriptor; 48] = [
+pub(crate) const LOGIN_PROVIDERS: [LoginProviderDescriptor; 49] = [
AUTO_IMPORT_LOGIN_PROVIDER,
CLAUDE_LOGIN_PROVIDER,
ANTHROPIC_API_LOGIN_PROVIDER,
@@ -1154,6 +1185,7 @@ pub(crate) const LOGIN_PROVIDERS: [LoginProviderDescriptor; 48] = [
CELERIS_LOGIN_PROVIDER,
LMSTUDIO_LOGIN_PROVIDER,
OLLAMA_LOGIN_PROVIDER,

  • OMNIROUTE_LOGIN_PROVIDER,
    OPENAI_COMPAT_LOGIN_PROVIDER,
    CURSOR_LOGIN_PROVIDER,
    COPILOT_LOGIN_PROVIDER,
    diff --git a/src/cli/args/tests.rs b/src/cli/args/tests.rs
    index 74c7714e4..67d90d60b 100644
    --- a/src/cli/args/tests.rs
    +++ b/src/cli/args/tests.rs
    @@ -49,6 +49,9 @@ fn test_provider_choice_aliases_parse() {

    let args = Args::try_parse_from(["jcode", "--provider", "cgc", "run", "smoke"]).unwrap();
    assert_eq!(args.provider, ProviderChoice::Comtegra);

  • let args = Args::try_parse_from(["jcode", "--provider", "omniroute", "run", "smoke"]).unwrap();

  • assert_eq!(args.provider, ProviderChoice::OmniRoute);
    }

#[test]
diff --git a/src/cli/commands/report_info.rs b/src/cli/commands/report_info.rs
index 2e9a77891..ee853829d 100644
--- a/src/cli/commands/report_info.rs
+++ b/src/cli/commands/report_info.rs
@@ -578,6 +578,7 @@ pub(super) fn list_cli_providers() -> Vec {
ProviderChoice::Chutes,
ProviderChoice::Cerebras,
ProviderChoice::AlibabaCodingPlan,

  •    ProviderChoice::OmniRoute,
       ProviderChoice::OpenaiCompatible,
       ProviderChoice::Cursor,
       ProviderChoice::Copilot,
    

diff --git a/src/cli/provider_init.rs b/src/cli/provider_init.rs
index 9fa2db29a..7b71eebe0 100644
--- a/src/cli/provider_init.rs
+++ b/src/cli/provider_init.rs
@@ -109,6 +109,11 @@ pub enum ProviderChoice {
alias = "alibaba-coding"
)]
AlibabaCodingPlan,

  • // Default clap name is omni-route (kebab of the variant); omniroute is
  • // the canonical provider id, so accept it as an alias alongside the short
  • // omni and the -ai qualifier.
  • #[value(alias = "omniroute", alias = "omni", alias = "omniroute-ai")]
  • OmniRoute,
    #[value(alias = "compat", alias = "custom")]
    OpenaiCompatible,
    Cursor,
    @@ -171,6 +176,7 @@ impl ProviderChoice {
    Self::Chutes => "chutes",
    Self::Cerebras => "cerebras",
    Self::AlibabaCodingPlan => "alibaba-coding-plan",
  •        Self::OmniRoute => "omniroute",
           Self::OpenaiCompatible => "openai-compatible",
           Self::Cursor => "cursor",
           Self::Copilot => "copilot",
    

@@ -349,6 +355,10 @@ const PROVIDER_CHOICE_LOGIN_PROVIDERS: &[(ProviderChoice, LoginProviderDescripto
ProviderChoice::AlibabaCodingPlan,
crate::provider_catalog::ALIBABA_CODING_PLAN_LOGIN_PROVIDER,
),

  • (
  •    ProviderChoice::OmniRoute,
    
  •    crate::provider_catalog::OMNIROUTE_LOGIN_PROVIDER,
    
  • ),
    (
    ProviderChoice::OpenaiCompatible,
    crate::provider_catalog::OPENAI_COMPAT_LOGIN_PROVIDER,
    @@ -1530,6 +1540,7 @@ async fn init_provider_with_options(
    | ProviderChoice::Chutes
    | ProviderChoice::Cerebras
    | ProviderChoice::AlibabaCodingPlan
  •    | ProviderChoice::OmniRoute
       | ProviderChoice::GeminiApi
       | ProviderChoice::OpenaiCompatible => {
           disable_subscription_runtime_mode();
    

diff --git a/src/cli/provider_init_tests.rs b/src/cli/provider_init_tests.rs
index f9858ea53..f193dbccb 100644
--- a/src/cli/provider_init_tests.rs
+++ b/src/cli/provider_init_tests.rs
@@ -440,6 +440,10 @@ fn choice_for_login_provider_round_trips_openai_compatible_profiles() {
choice_for_login_provider(provider_catalog::OPENAI_COMPAT_LOGIN_PROVIDER),
Some(ProviderChoice::OpenaiCompatible)
);

  • assert_eq!(
  •    choice_for_login_provider(provider_catalog::OMNIROUTE_LOGIN_PROVIDER),
    
  •    Some(ProviderChoice::OmniRoute)
    
  • );
    }

#[test]
@@ -825,6 +829,7 @@ async fn auto_provider_noninteractive_skips_untrusted_external_auth_instead_of_b
"ANTHROPIC_API_KEY",
"OPENAI_API_KEY",
"OPENROUTER_API_KEY",

  •    "OMNIROUTE_API_KEY",
       "GITHUB_TOKEN",
       "GEMINI_API_KEY",
       "CURSOR_API_KEY",
    

@@ -843,6 +848,7 @@ async fn auto_provider_noninteractive_skips_untrusted_external_auth_instead_of_b
"ANTHROPIC_API_KEY",
"OPENAI_API_KEY",
"OPENROUTER_API_KEY",

  •    "OMNIROUTE_API_KEY",
       "GITHUB_TOKEN",
       "GEMINI_API_KEY",
       "CURSOR_API_KEY",
    

--
2.43.0

</details>

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with crates/jcode-provider-metadata/src/catalog.rs and the existing openrouter, deepseek, kimi, ollama, and lmstudio profiles, then trace ProviderChoice in src/cli/provider_init.rs and provider listing in src/cli/commands/report_info.rs. Update the named README and test files following the existing pattern, then run the provider metadata, CLI argument, and provider initialization tests; done means the profile, aliases, login surfaces, and no-credentials fixture pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend-api-design, cli
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.