Skip to content

Commit e28e397

Browse files
Initial commit
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
0 parents  commit e28e397

349 files changed

Lines changed: 78287 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# CCProxy Configuration
2+
# Copy this file to .env and customize as needed
3+
4+
# =============================================================================
5+
# SERVER CONFIGURATION
6+
# =============================================================================
7+
# Server settings use the SERVER__ prefix (pydantic-settings nested config)
8+
9+
SERVER__HOST=0.0.0.0
10+
SERVER__PORT=8000
11+
SERVER__LOG_LEVEL=INFO
12+
# SERVER__LOG_FILE=/var/log/ccproxy/ccproxy.log
13+
14+
# =============================================================================
15+
# MULTI-ACCOUNT ROTATION
16+
# =============================================================================
17+
# Path to accounts.json file with OAuth credentials
18+
# Must be absolute path or start with ~
19+
# CCPROXY_ACCOUNTS_PATH=/path/to/accounts.json
20+
21+
# Enable/disable multi-account rotation (default: true if accounts.json exists)
22+
# CCPROXY_ROTATION_ENABLED=true
23+
24+
# Enable/disable hot reload of accounts.json changes (default: true)
25+
# CCPROXY_HOT_RELOAD=true
26+
27+
# =============================================================================
28+
# DOCKER CONFIGURATION
29+
# =============================================================================
30+
# User/Group ID mapping for Docker to avoid permission issues
31+
# Find your IDs with: id -u && id -g
32+
PUID=1000
33+
PGID=1000
34+
35+
# Config directory to mount in Docker (default: ~/.claude)
36+
# CCPROXY_CONFIG_DIR=~/.claude
37+
38+
# Hostname for Traefik routing (Docker compose with Traefik)
39+
# CCPROXY_HOST=localhost
40+
41+
# =============================================================================
42+
# UI SECURITY (Traefik Basic Auth)
43+
# =============================================================================
44+
# Basic Auth credentials for /accounts UI (protects account management)
45+
# Generate with: htpasswd -nb username password
46+
# Example: htpasswd -nb admin mySecurePassword123
47+
# IMPORTANT: In docker-compose, escape $ as $$ (admin:$$apr1$$...)
48+
# CCPROXY_UI_AUTH=admin:$$apr1$$SALT$$HASH
49+
50+
# =============================================================================
51+
# DEBUGGING & LOGGING
52+
# =============================================================================
53+
# Enable verbose API logging (shows full request/response)
54+
# CCPROXY_VERBOSE_API=false
55+
56+
# Enable verbose streaming logging
57+
# CCPROXY_VERBOSE_STREAMING=false
58+
59+
# Enable request logging to files
60+
# CCPROXY_LOG_REQUESTS=false
61+
62+
# Directory for request log files (only used if CCPROXY_LOG_REQUESTS=true)
63+
# CCPROXY_REQUEST_LOG_DIR=/tmp/ccproxy/requests
64+
65+
# =============================================================================
66+
# OAUTH CONFIGURATION
67+
# =============================================================================
68+
# Custom OAuth redirect URI (for remote deployments)
69+
# CCPROXY_OAUTH_REDIRECT_URI=http://localhost:54545/callback
70+
71+
# =============================================================================
72+
# CAPACITY CHECKING
73+
# =============================================================================
74+
# URL for capacity check requests
75+
# CCPROXY_CAPACITY_CHECK_URL=http://localhost:8000/api/v1/messages
76+
77+
# Model to use for capacity check requests
78+
# CCPROXY_CAPACITY_CHECK_MODEL=claude-sonnet-4-20250514
79+
80+
# =============================================================================
81+
# PROXY & SSL CONFIGURATION
82+
# =============================================================================
83+
# HTTP/HTTPS proxy settings (standard environment variables)
84+
# HTTPS_PROXY=http://proxy.example.com:8080
85+
# HTTP_PROXY=http://proxy.example.com:8080
86+
# ALL_PROXY=socks5://proxy.example.com:1080
87+
88+
# Custom CA bundle for SSL verification
89+
# REQUESTS_CA_BUNDLE=/path/to/ca-bundle.crt
90+
# SSL_CERT_FILE=/path/to/cert.pem
91+
92+
# Disable SSL verification (not recommended for production)
93+
# SSL_VERIFY=true
94+
95+
# =============================================================================
96+
# SDK CLIENT CONFIGURATION
97+
# =============================================================================
98+
# These are set automatically when using the proxy, but can be set manually
99+
# for external SDK clients connecting to your proxy
100+
101+
# Auth token for API access (generated on server start)
102+
# ANTHROPIC_API_KEY=your_token_here
103+
104+
# Base URL for Anthropic SDK clients
105+
# ANTHROPIC_BASE_URL=http://localhost:8000

.github/workflows/backend.yml

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
name: Backend CI
2+
3+
on:
4+
push:
5+
branches: [main, dev]
6+
paths:
7+
- "claude-code-proxy/**"
8+
- "tests/**"
9+
- "pyproject.toml"
10+
- "uv.lock"
11+
- "Makefile"
12+
- ".github/workflows/backend.yml"
13+
pull_request:
14+
branches: [main, dev]
15+
paths:
16+
- "claude-code-proxy/**"
17+
- "tests/**"
18+
- "pyproject.toml"
19+
- "uv.lock"
20+
- "Makefile"
21+
- ".github/workflows/backend.yml"
22+
workflow_dispatch:
23+
24+
jobs:
25+
quality-checks:
26+
runs-on: ubuntu-latest
27+
name: Quality Checks (ruff + mypy)
28+
29+
steps:
30+
- name: Checkout code
31+
uses: actions/checkout@v4
32+
33+
- name: Install uv
34+
uses: astral-sh/setup-uv@v4
35+
with:
36+
enable-cache: true
37+
38+
- name: Set up Python
39+
run: uv python install
40+
41+
- name: Install dependencies
42+
run: make dev-install
43+
44+
- name: Cache mypy
45+
uses: actions/cache@v4
46+
with:
47+
path: .mypy_cache
48+
key: mypy-${{ runner.os }}-${{ hashFiles('pyproject.toml', 'uv.lock') }}
49+
restore-keys: |
50+
mypy-${{ runner.os }}-
51+
52+
- name: Run quality checks
53+
run: make check
54+
55+
tests:
56+
runs-on: ubuntu-latest
57+
name: Tests
58+
needs: quality-checks
59+
60+
strategy:
61+
matrix:
62+
python-version: ["3.11", "3.12"]
63+
64+
steps:
65+
- name: Checkout code
66+
uses: actions/checkout@v4
67+
68+
- name: Install uv
69+
uses: astral-sh/setup-uv@v4
70+
with:
71+
enable-cache: true
72+
73+
- name: Set up Python ${{ matrix.python-version }}
74+
run: uv python install ${{ matrix.python-version }}
75+
76+
- name: Install dependencies
77+
run: make dev-install
78+
79+
- name: Run unit tests
80+
run: make test-unit
81+
82+
- name: Upload coverage reports
83+
if: matrix.python-version == '3.11'
84+
uses: codecov/codecov-action@v4
85+
with:
86+
files: ./coverage.xml
87+
fail_ci_if_error: false
88+
env:
89+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
90+
91+
build-verification:
92+
runs-on: ubuntu-latest
93+
name: Build Verification
94+
needs: quality-checks
95+
96+
steps:
97+
- name: Checkout code
98+
uses: actions/checkout@v4
99+
100+
- name: Install uv
101+
uses: astral-sh/setup-uv@v4
102+
with:
103+
enable-cache: true
104+
105+
- name: Set up Python
106+
run: uv python install
107+
108+
- name: Install dependencies
109+
run: make dev-install
110+
111+
- name: Test package build
112+
run: make build-backend
113+
114+
- name: Verify CLI installation
115+
run: |
116+
uv run claude-code-proxy --version
117+
uv run claude-code-proxy --help

.github/workflows/build.yml

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
name: Build Docker Images
2+
3+
on:
4+
push:
5+
branches: [main]
6+
workflow_run:
7+
workflows: ["CI"]
8+
types: [completed]
9+
branches: [main]
10+
workflow_dispatch:
11+
12+
env:
13+
REGISTRY: ghcr.io
14+
IMAGE_NAME: ${{ github.repository }}
15+
16+
jobs:
17+
build-docker:
18+
runs-on: ubuntu-latest
19+
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' || (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
20+
21+
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
22+
permissions:
23+
contents: read
24+
packages: write
25+
attestations: write
26+
id-token: write
27+
28+
steps:
29+
- name: Checkout repository
30+
uses: actions/checkout@v4
31+
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
32+
- name: Log in to the Container registry
33+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
34+
with:
35+
registry: ${{ env.REGISTRY }}
36+
username: ${{ github.actor }}
37+
password: ${{ secrets.GITHUB_TOKEN }}
38+
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
39+
- name: Extract metadata (tags, labels) for Docker
40+
id: meta
41+
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
42+
with:
43+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
44+
# generate Docker tags based on the following events/attributes
45+
tags: |
46+
type=raw,value=latest,enable={{is_default_branch}}
47+
type=schedule
48+
type=ref,event=branch
49+
type=ref,event=pr
50+
type=semver,pattern={{version}}
51+
type=semver,pattern={{major}}.{{minor}}
52+
type=semver,pattern={{major}}
53+
type=sha
54+
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
55+
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see [Usage](https://github.com/docker/build-push-action#usage) in the README of the `docker/build-push-action` repository.
56+
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
57+
- name: Build and push Docker image
58+
id: push
59+
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
60+
with:
61+
context: .
62+
file: docker/Dockerfile
63+
push: true
64+
tags: ${{ steps.meta.outputs.tags }}
65+
labels: ${{ steps.meta.outputs.labels }}
66+
67+
# This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see [Using artifact attestations to establish provenance for builds](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds).
68+
- name: Generate artifact attestation
69+
uses: actions/attest-build-provenance@v2
70+
with:
71+
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
72+
subject-digest: ${{ steps.push.outputs.digest }}
73+
push-to-registry: true
74+
75+
# Set environment variables in Coolify before deployment
76+
- name: Configure Coolify environment
77+
env:
78+
COOLIFY_WEBHOOK_URL: ${{ secrets.COOLIFY_WEBHOOK_URL }}
79+
COOLIFY_TOKEN: ${{ secrets.COOLIFY_TOKEN }}
80+
CCPROXY_UI_AUTH: ${{ secrets.CCPROXY_UI_AUTH }}
81+
run: |
82+
if [ -n "$COOLIFY_WEBHOOK_URL" ] && [ -n "$COOLIFY_TOKEN" ] && [ -n "$CCPROXY_UI_AUTH" ]; then
83+
# Extract base URL and UUID from webhook URL
84+
# Webhook format: https://coolify.domain.com/api/v1/deploy?uuid=xxxx&force=false
85+
COOLIFY_BASE_URL=$(echo "$COOLIFY_WEBHOOK_URL" | sed 's|/api/v1/deploy.*||')
86+
SERVICE_UUID=$(echo "$COOLIFY_WEBHOOK_URL" | grep -oP 'uuid=\K[^&]+')
87+
88+
if [ -n "$SERVICE_UUID" ]; then
89+
echo "Setting CCPROXY_UI_AUTH for service $SERVICE_UUID"
90+
curl -s -X PATCH "${COOLIFY_BASE_URL}/api/v1/services/${SERVICE_UUID}/envs" \
91+
-H "Authorization: Bearer $COOLIFY_TOKEN" \
92+
-H "Content-Type: application/json" \
93+
-d "{\"key\": \"CCPROXY_UI_AUTH\", \"value\": \"${CCPROXY_UI_AUTH}\", \"is_build_time\": false}" \
94+
&& echo "✅ Environment variable set" || echo "⚠️ Failed to set env var (non-blocking)"
95+
else
96+
echo "⚠️ Could not extract service UUID from webhook URL"
97+
fi
98+
else
99+
echo "ℹ️ Skipping env var setup (missing secrets)"
100+
fi
101+
102+
# Trigger Coolify deployment webhook
103+
- name: Deploy to Coolify
104+
env:
105+
COOLIFY_WEBHOOK_URL: ${{ secrets.COOLIFY_WEBHOOK_URL }}
106+
COOLIFY_TOKEN: ${{ secrets.COOLIFY_TOKEN }}
107+
run: |
108+
if [ -n "$COOLIFY_WEBHOOK_URL" ] && [ -n "$COOLIFY_TOKEN" ]; then
109+
curl -X POST "$COOLIFY_WEBHOOK_URL" \
110+
-H "Authorization: Bearer $COOLIFY_TOKEN" \
111+
-H "Content-Type: application/json" \
112+
&& echo "✅ Coolify deployment triggered" || echo "⚠️ Coolify webhook failed (non-blocking)"
113+
else
114+
echo "ℹ️ COOLIFY_WEBHOOK_URL or COOLIFY_TOKEN not configured, skipping deployment"
115+
fi

.github/workflows/ci.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main, develop]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
python-version: ["3.11", "3.12", "3.13"]
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- uses: oven-sh/setup-bun@v2
20+
21+
- name: Install uv
22+
uses: astral-sh/setup-uv@v3
23+
with:
24+
enable-cache: true
25+
26+
- name: Set up Python ${{ matrix.python-version }}
27+
run: uv python install ${{ matrix.python-version }}
28+
29+
- name: Install dependencies
30+
run: make dev-install
31+
32+
- name: Run CI pipeline
33+
run: make ci
34+
35+
- name: Build documentation
36+
run: make docs-build
37+
38+
- name: Upload coverage reports
39+
uses: codecov/codecov-action@v4
40+
with:
41+
file: ./coverage.xml
42+
flags: unittests
43+
name: codecov-umbrella
44+
fail_ci_if_error: false

0 commit comments

Comments
 (0)