Internal Claude gateway control layer and developer CLI
Project description
Claude Control Layer
FastAPI control plane for Claude/LiteLLM access with users, roles, teams, runtime policy settings, quota metadata, usage analytics, alerts, and admin APIs.
Claude Code no longer points directly at the FastAPI app for Anthropic-compatible transport. Claude Code points at LiteLLM, while this app manages the surrounding control-plane data and can create LiteLLM virtual keys for users.
Features
- Role-based model enforcement for
admin,engineer, andworker - Daily token quota checks per user
- Full usage logging in Postgres
- Admin analytics for overview, users, models, trends, and estimated cost
- Token-based admin authentication with login
- LiteLLM proxy service for Claude Code transport
- LiteLLM virtual-key creation from admin-managed users, roles, and teams
- Redis client wiring for future rate-limiting or caching work
- Dockerized local development
Project layout
app/
core/
models/
routes/
schemas/
services/
docker/
migrations/
admin-dashboard/
Run locally with Docker
docker-compose up --build
The API will be available at http://localhost:8000.
LiteLLM will be available at http://localhost:4000.
API endpoints
POST /chatPOST /auth/loginPOST /auth/claude-code-tokenPOST /v1/messagesPOST /v1/messages/count_tokensGET /healthGET /auth/meGET /admin/overviewGET /admin/usersGET /admin/trendsGET /admin/modelsGET /admin/cost
POST /chat, POST /v1/messages, and POST /v1/messages/count_tokens are legacy FastAPI transport endpoints and are disabled by default. Set ENABLE_LEGACY_CLAUDE_TRANSPORT=true only for a temporary migration window.
POST /auth/claude-code-token is deprecated and returns 410 Gone. Claude Code should use a LiteLLM virtual key instead.
Admins can create a LiteLLM virtual key for an app user with:
POST /admin/users/{user_id}/litellm-key
Admin auth
Admin routes accept bearer tokens returned by POST /auth/login. The dashboard now requires login before loading / or /settings.
On a fresh Postgres volume, Docker seeds an admin user automatically:
username/id: anase
password: numnum2001
role: admin
Use a strong AUTH_SECRET in .env for production deployments.
For local dashboard access, keep ALLOWED_ORIGINS aligned with the frontend URL. By default it allows:
http://localhost:3000
http://127.0.0.1:3000
Example chat request
{
"user_id": "u_123",
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Summarize the latest deployment notes."
}
]
}
LiteLLM Transport
LiteLLM runs as a separate service in Docker Compose and listens on port 4000.
The local LiteLLM config is:
litellm/config.yaml
It uses:
- Postgres-backed LiteLLM key management through
DATABASE_URL LITELLM_MASTER_KEYfor admin/control-plane callsx-litellm-api-keyas the virtual-key headerclaude-code-sonnetas the local default model name
For local development, configure these in .env:
LITELLM_PROXY_URL=http://localhost:4000
LITELLM_INTERNAL_URL=http://litellm:4000
LITELLM_MASTER_KEY=sk-local-litellm-master-key
LITELLM_DEFAULT_MODEL=claude-code-sonnet
ENABLE_LEGACY_CLAUDE_TRANSPORT=false
Developer CLI
The company-ai CLI lets developers configure Claude Code to use LiteLLM while the FastAPI app remains the admin/control plane.
Install from PyPI:
pip install --upgrade company-ai
Install the Python requirements first:
pip install -r requirements.txt
For a real company-ai command on PATH, install the local package:
pip install -e .
Check the installed version:
company-ai --version
Log in once:
company-ai login --gateway http://localhost:8000
The CLI prompts for email and password, calls POST /auth/login, stores the app session token in the OS keychain through keyring, and saves non-secret config in:
~/.config/company-ai/config.json
Configure Claude Code:
company-ai setup-claude --litellm-url http://localhost:4000 --litellm-key sk-your-user-virtual-key --model claude-code-sonnet
This safely updates:
~/.claude/settings.json
with:
{
"env": {
"ANTHROPIC_BASE_URL": "http://localhost:4000",
"ANTHROPIC_CUSTOM_HEADERS": "x-litellm-api-key: Bearer sk-your-user-virtual-key",
"ANTHROPIC_MODEL": "claude-code-sonnet"
}
}
Claude Code should remain logged in with Claude subscription auth client-side. The LiteLLM virtual key is sent separately in ANTHROPIC_CUSTOM_HEADERS.
Releasing the CLI
Release notes and tag/publish steps live in RELEASING.md.
Claude Subscription Limit Breaker
Claude Code traffic is protected by a global subscription-limit circuit breaker. This is separate from app quotas and model policy. It represents the real upstream Claude subscription lockout, such as the Claude Max 5-hour plan limit.
The flow is:
- LiteLLM forwards Claude Code traffic upstream.
- If the upstream provider returns a subscription-limit/reset error, the LiteLLM callback reports the sanitized error to FastAPI at
POST /internal/litellm/subscription-limit. - FastAPI stores an active block in
system_runtime_blockswith the reasonclaude_subscription_limit_reached, the detected time, sanitized upstream message, and a parsed UTC reset time when available. - The LiteLLM policy check at
POST /internal/litellm/policychecks this block before local quotas, model policy, and request guardrails. - While the block is active, new Claude requests are rejected before any upstream call with a fatal terminal message that includes the reset time when known.
- The Alerts page shows a critical alert titled
Team reached Claude subscription limit. - If
reset_atis known, the block clears automatically after that time on the next policy/admin check. If the reset time is unknown, an admin can clear it manually after verifying Claude access has recovered.
Admin endpoints:
GET /admin/system/subscription-limit-state
POST /admin/system/subscription-limit-state/clear
POST /admin/system/subscription-limit-state/probe
The probe endpoint reports the current state. In Claude subscription mode the server cannot perform a real upstream probe without client-side Claude Code subscription credentials, so unknown-reset blocks should be cleared manually after a user confirms Claude works again.
You can also provide setup values through environment variables:
COMPANY_AI_LITELLM_URL=http://localhost:4000
COMPANY_AI_LITELLM_KEY=sk-your-user-virtual-key
COMPANY_AI_LITELLM_MODEL=claude-code-sonnet
After setup, run:
claude
Then verify with /status.
To remove the stored app session:
company-ai logout
Dashboard
A minimal Next.js dashboard is included under admin-dashboard/.
cd admin-dashboard
npm install
npm run dev
Project details
Release history Release notifications | RSS feed
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 company_ai-0.2.0.tar.gz.
File metadata
- Download URL: company_ai-0.2.0.tar.gz
- Upload date:
- Size: 16.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bfda64d4785c389ffd45ed19d8f08122ea670bbbb9a23b70a5a702190ea7e7af
|
|
| MD5 |
dc378827b671a1b9baae16e9329c7587
|
|
| BLAKE2b-256 |
d7d0cf52e239f5d3c696f93c404212a3ff9211bd4d38d5822e92c71bd838f0f3
|
Provenance
The following attestation bundles were made for company_ai-0.2.0.tar.gz:
Publisher:
publish-pypi.yml on ElharrariAnas/Claude-Control-layer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
company_ai-0.2.0.tar.gz -
Subject digest:
bfda64d4785c389ffd45ed19d8f08122ea670bbbb9a23b70a5a702190ea7e7af - Sigstore transparency entry: 1364521425
- Sigstore integration time:
-
Permalink:
ElharrariAnas/Claude-Control-layer@a2bc51e568e44624e827388322b416ae91be06b5 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/ElharrariAnas
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@a2bc51e568e44624e827388322b416ae91be06b5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file company_ai-0.2.0-py3-none-any.whl.
File metadata
- Download URL: company_ai-0.2.0-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b4548366ae4786ad02d5e057e826507e930c8697827e18f76ecf6551c5b6fe2
|
|
| MD5 |
f9ba22e0db847249a9e4cc56c96183ec
|
|
| BLAKE2b-256 |
c690a341b37bb9aec3f240b8cbb3c0cf16beba9bc7c8ddde6779cf50fb326ed6
|
Provenance
The following attestation bundles were made for company_ai-0.2.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on ElharrariAnas/Claude-Control-layer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
company_ai-0.2.0-py3-none-any.whl -
Subject digest:
8b4548366ae4786ad02d5e057e826507e930c8697827e18f76ecf6551c5b6fe2 - Sigstore transparency entry: 1364521435
- Sigstore integration time:
-
Permalink:
ElharrariAnas/Claude-Control-layer@a2bc51e568e44624e827388322b416ae91be06b5 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/ElharrariAnas
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@a2bc51e568e44624e827388322b416ae91be06b5 -
Trigger Event:
push
-
Statement type: