Skip to content

Add litellm-proxy plugin with comprehensive setup and configuration skills - #203

Open
nsheaps wants to merge 8 commits into
mainfrom
claude/light-llm-proxy-plugin-UnIfH
Open

nsheaps wants to merge 8 commits into
mainfrom
claude/light-llm-proxy-plugin-UnIfH

Conversation

@nsheaps

@nsheaps nsheaps commented Feb 26, 2026

Copy link
Copy Markdown
Owner

What

Added a new litellm-proxy Claude Code plugin that auto-detects and configures a LiteLLM proxy on session start. The plugin includes:

  • SessionStart hook (session-start.sh) that detects running LiteLLM proxies (local or remote) and automatically configures Claude Code to route through them
  • Five comprehensive skills for interactive setup and configuration:
    • setup-litellm: Install and start LiteLLM proxy
    • configure-providers: Add/manage LLM providers (Anthropic, OpenAI, Gemini, Bedrock, Azure, etc.)
    • configure-observability: Set up traces, logs, and metrics (Langfuse, OpenTelemetry, Datadog, Prometheus)
    • configure-claude-code: Wire Claude Code to use the proxy
    • configure-remote-proxy: Connect to remote proxies or Cloudflare AI Gateway
  • Configuration system supporting project-level, user-level, and plugin-level settings with secret resolution (env vars, 1Password)
  • Template config file for LiteLLM with common provider examples
  • Shared library (safe-settings-write.sh) for atomic, concurrent-safe settings file updates

Why

LiteLLM is a powerful AI gateway that enables:

  • Multi-provider routing (use multiple Anthropic accounts, OpenAI, Gemini, Bedrock simultaneously)
  • Load balancing and failover across providers
  • Observability and cost tracking
  • Unified API interface

This plugin makes it seamless for Claude Code users to leverage LiteLLM without manual configuration, while providing comprehensive guides for advanced setup scenarios.

How

The implementation follows the Claude Code plugin architecture:

  1. SessionStart hook reads YAML configuration (project → user → plugin defaults), checks proxy health, and writes ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN to ~/.claude/settings.local.json
  2. Skills provide interactive, step-by-step guidance for each configuration aspect with code examples and troubleshooting
  3. Config resolution supports environment variable references (${VAR_NAME}), 1Password references (op://vault/item/field), and literal values
  4. Safe settings writer uses POSIX-compliant mkdir-based locking for concurrent-safe JSON updates
  5. Multiple modes (auto, local, remote, gateway, disabled) support different deployment scenarios

Validation steps

  • Plugin structure follows Claude Code plugin conventions (.claude-plugin/plugin.json, hooks, skills)
  • SessionStart hook correctly reads YAML config with fallback chain
  • Secret resolution handles env vars, 1Password, and literals
  • Health check logic properly detects proxy availability
  • Settings writer uses atomic operations with lock-based concurrency control
  • Skills provide complete, actionable guidance with code examples
  • Template config includes common providers with clear examples
  • README documents quick start, configuration, and modes

Additional Context

This plugin enables the use case where users want to:

  • Route Claude Code through a local LiteLLM proxy for multi-provider load balancing
  • Connect to a shared team LiteLLM instance
  • Use Cloudflare AI Gateway or other compatible gateways
  • Track costs and observability across LLM calls
  • Manage multiple API keys and providers from a single configuration

The plugin gracefully handles missing proxies (auto mode) and provides clear guidance through skills when setup is needed.

https://claude.ai/code/session_01KqUVPTGpmvGdPSu9ZeQxNe

@github-actions

github-actions Bot commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

Plugin Version Status

Versions are auto-bumped in PRs. Manual bumps to higher versions are preserved.

Plugin Base Current Action
mise 0.2.18 0.2.19 Already bumped
poc-litellm-proxy 0.0.0 0.1.0 Already bumped

henry-nsheaps[bot]

This comment was marked as outdated.

henry-nsheaps[bot]

This comment was marked as outdated.

henry-nsheaps[bot]

This comment was marked as outdated.

claude and others added 6 commits March 25, 2026 00:20
… comprehensive skills

New plugin that auto-configures Claude Code to route through a LiteLLM proxy
on session start. Supports local/remote proxy modes, Cloudflare AI Gateway,
and multi-provider routing with observability.

Plugin includes:
- SessionStart hook for proxy detection and ANTHROPIC_BASE_URL configuration
- 5 skills: setup-litellm, configure-providers, configure-observability,
  configure-remote-proxy, configure-claude-code
- Config template for LiteLLM proxy with all major providers
- Plugin settings with env var, 1Password, and literal secret resolution
- Support for pass-through (/anthropic) and unified endpoints

https://claude.ai/code/session_01KqUVPTGpmvGdPSu9ZeQxNe
…-write

Replace settings.local.json writes with CLAUDE_ENV_FILE exports, which is
the proper session-scoped mechanism for SessionStart hooks. Remove the
safe-settings-write.sh shared lib dependency.

https://claude.ai/code/session_01KqUVPTGpmvGdPSu9ZeQxNe
…d secret resolution

Create shared/lib/plugin-config.sh providing:
- plugin_config(): three-level YAML config resolution (project → user → plugin defaults)
- plugin_resolve_secret(): env var, 1Password, and literal secret resolution
- plugin_is_enabled(): convenience check

Update litellm-proxy and datadog-otel-setup to use the shared lib instead of
duplicating read_config_key/get_config/resolve_secret functions inline.

https://claude.ai/code/session_01KqUVPTGpmvGdPSu9ZeQxNe
Rename plugin directory, plugin.json name, YAML config keys, settings
file, log prefixes, and all documentation references.

https://claude.ai/code/session_01KqUVPTGpmvGdPSu9ZeQxNe
@nsheaps
nsheaps force-pushed the claude/light-llm-proxy-plugin-UnIfH branch from 5501022 to 57b9113 Compare March 25, 2026 00:21
henry-nsheaps[bot]

This comment was marked as outdated.

henry-nsheaps[bot]

This comment was marked as outdated.

@henry-nsheaps henry-nsheaps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ Two blocking issues remain unaddressed since prior reviews: camelCase settings keys and symlinks for shared libs

❌ Settings keys use snake_case — must be camelCase per repo convention (thread)
plugin-config.sh is a copy in poc-litellm-proxy/lib/ and mise/lib/ — should be symlinks (thread 1, thread 2 in this review)
⚠️ memory.jsonl has stale observations after refactoring (thread)
⚠️ write_env quoting could break on special characters (thread)
✅ Secure secret resolution via indirect expansion, no eval
✅ Plugin structure follows conventions (hooks.json, skills, plugin.json)
✅ CLAUDE_ENV_FILE usage is the correct session-scoped pattern
✅ Config resolution chain (project → user → plugin defaults) is clean
✅ Graceful degradation when yq/curl/docker not available

🖱️ Click to expand for full details

No Code Changes Since Last Review

The only new commit (59526c9) is a merge from main. All plugin code is unchanged from 32fde1f. The two blocking issues and three warnings from the previous review remain unaddressed.

Code Quality (70%)

The plugin itself is well-structured with solid shell scripting practices. Two convention violations keep the score down:

1. Settings key naming (❌ blocking): All multi-word settings keys use snake_case (proxy_host, proxy_port, master_key, config_path, remote_url, anthropic_pass_through) but .claude/rules/settings-key-naming.md explicitly requires camelCase. This affects the settings YAML, session-start.sh plugin_config() calls, README, and all 5 skill files. Keys should be: proxyHost, proxyPort, masterKey, configPath, remoteUrl, anthropicPassThrough.

2. Shared lib copies instead of symlinks (❌ blocking): Both plugins/poc-litellm-proxy/lib/plugin-config.sh and plugins/mise/lib/plugin-config.sh are regular files (mode 100755, 4400 bytes each) — not symlinks. Per .claude/rules/shared-libs.md: "Symlink into each plugin that needs it." All other shared libs in the repo follow this pattern.

Security (95%)

Strong practices throughout:

  • Secret resolution uses ${!var_name:-} (indirect expansion) — no eval, no command injection vectors
  • Regex anchoring (^\$\{...\}$) ensures only full env var references are matched
  • API keys never stored in plugin source
  • Environment variables set via CLAUDE_ENV_FILE (session-scoped, not persisted)
  • 1Password integration (op://) for enterprise secret management

Simplicity (90%)

Code is straightforward and avoids over-engineering. Functions are small and focused. The case statement for mode handling is easy to follow. The config resolution chain is a clean pattern.

Confidence (95%)

Verified via git log that no plugin code changed since the last review (only a merge from main). Confirmed file types with ls -la (regular files, not symlinks). Cross-referenced all 16 existing review threads and their resolution states. All 5 previous reviews minimized as outdated.

Previous Review Status

Previous Issue Current Status
safe-settings-write.sh copy vs symlink ✅ Resolved — refactored to CLAUDE_ENV_FILE
plugin-config.sh copy vs symlink ❌ Still unaddressed
camelCase settings keys ❌ Still unaddressed
memory.jsonl stale observations ⚠️ Still unaddressed
write_env quoting concern ⚠️ Still unaddressed
Docker image inspect perf ⏳ Non-blocking, unchanged

Recommended follow-ups (non-blocking):

  • The Docker image inspect check in check_litellm_installed() could be slow if the daemon is unresponsive. Consider a timeout or caching if users report slow session starts.
  • Consider adding yq to mise.toml since this plugin and the shared config lib depend on it (even though they degrade gracefully without it).
  • The existing shared/lib/plugin-config-read.sh also provides config reading. Consider documenting the relationship or consolidating with the new plugin-config.sh.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same DRY issue: this should be a symlink, not a copy.

This file is a byte-for-byte copy of shared/lib/plugin-config.sh (both 4400 bytes, same git blob 2a2502e). Per .claude/rules/shared-libs.md: "Symlink into each plugin that needs it."

All other shared libs in the repo use symlinks (e.g., safe-settings-write.sh → ../../../shared/lib/safe-settings-write.sh).

See also: same issue on poc-litellm-proxy/lib/plugin-config.sh

Fix:

rm plugins/mise/lib/plugin-config.sh
ln -s ../../../shared/lib/plugin-config.sh plugins/mise/lib/plugin-config.sh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants