Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ezswitch

Terminal UI for switching local AI tool providers without hand-editing config files every time you move between DeepSeek, OpenRouter, a team gateway, or a local endpoint.

ezswitch TUI screenshot

What It Does

ezswitch keeps provider profiles under ~/.config/ezswitch/, lets you edit them in a Textual interface, and asks each app plugin to write the selected provider into the target tool's native config.

Built-in app plugins:

  • codex updates ~/.codex/config.toml and ~/.codex/auth.json.
  • claude updates ~/.claude/settings.json.

The UI disables Switch when the selected app does not appear to be installed. Plugins declare this with requires_cli and requires_path, so custom plugins can adapt the same check for local tools, wrappers, or gateway CLIs.

Install

uv tool install .

This installs the ezswitch launcher into uv's tool bin directory, usually ~/.local/bin. Make sure that directory is on your PATH.

For development:

uv run ezswitch
uv run pytest

First Run

ezswitch

On startup, ezswitch creates:

~/.config/ezswitch/
~/.config/ezswitch/apps/
~/.config/ezswitch/codex.providers.json
~/.config/ezswitch/claude.providers.json

Existing provider files are never overwritten during initialization.

Provider Files

Provider files are JSON objects named {app}.providers.json.

{
  "name": "codex",
  "active": "8b3f6d7e-4c17-4f7c-8f7a-9bb2d83c9a3d",
  "providers": {
    "8b3f6d7e-4c17-4f7c-8f7a-9bb2d83c9a3d": {
      "name": "openrouter",
      "base_url": "https://openrouter.ai/api/",
      "api_key": "...",
      "model": "anthropic/claude-sonnet-4.5",
      "model_list": [
        "anthropic/claude-sonnet-4.5",
        "openai/gpt-5"
      ],
      "note": "shared fallback provider"
    }
  }
}

Sync tries the OpenAI-compatible models endpoint and stores data[*].id into model_list. For base URLs like https://openrouter.ai/api/, it tries:

https://openrouter.ai/v1/models
https://openrouter.ai/api/v1/models

Selecting a model writes it back to the provider's model field. Clear empties the cached model list.

Custom App Plugins

User plugins live in ~/.config/ezswitch/apps/{name}.py and override built-ins with the same filename.

from ezswitch.core.plugins import AppPlugin
from ezswitch.core.editors import JsonEditor


class MyTool(AppPlugin):
    display_name = "My Tool"
    description = "Patch My Tool provider settings"
    requires_cli = ("my-tool",)
    requires_path = ("~/.my-tool",)

    def switch(self, provider):
        config = JsonEditor("~/.my-tool/settings.json")
        config.update("base_url", provider.base_url)
        config.update("api_key", provider.api_key)
        config.update("model", provider.model)

If requires_cli or requires_path is not satisfied, the app remains visible but switching is disabled with a toast message.

Screenshot

The README image lives at docs/ezswitch.png. Regenerate it from a clean temporary config whenever the TUI layout changes.

About

Switch AI provider configs across local tools from a terminal UI.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages