### Install CliRelay with Docker Compose
Source: https://github.com/kittors/clirelay/blob/main/README.md
Use these commands to clone the repository, set up the configuration, and start CliRelay using Docker Compose. Ensure you edit `config.yaml` after setup.
```bash
git clone https://github.com/kittors/CliRelay.git
cd CliRelay
cp config.example.yaml config.yaml
docker compose up -d
```
```bash
docker compose restart cli-proxy-api
```
--------------------------------
### Install CLIProxyAPI SDK
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md
Install the SDK using go get. Ensure you use the correct module path including /v6.
```bash
go get github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy
```
--------------------------------
### CLI Proxy Service with Hooks
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md
Attach lifecycle hooks to the CLI proxy service to observe events like starting and readiness.
```go
hooks := cliproxy.Hooks{
OnBeforeStart: func(cfg *config.Config) { log.Infof("starting on :%d", cfg.Port) },
OnAfterStart: func(s *cliproxy.Service) { log.Info("ready") },
}
svc, _ := cliproxy.NewBuilder().WithConfig(cfg).WithConfigPath("config.yaml").WithHooks(hooks).Build()
```
--------------------------------
### Writing Custom Providers
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md
Provides an example and requirements for writing and registering custom access providers.
```APIDOC
## Writing Custom Providers
```go
type customProvider struct{}
func (p *customProvider) Identifier() string { return "my-provider" }
func (p *customProvider) Authenticate(ctx context.Context, r *http.Request) (*sdkaccess.Result, *sdkaccess.AuthError) {
token := r.Header.Get("X-Custom")
if token == "" {
return nil, sdkaccess.NewNotHandledError()
}
if token != "expected" {
return nil, sdkaccess.NewInvalidCredentialError()
}
return &sdkaccess.Result{
Provider: p.Identifier(),
Principal: "service-user",
Metadata: map[string]string{"source": "x-custom"},
}, nil
}
func init() {
sdkaccess.RegisterProvider("custom", &customProvider{})
}
```
A provider must implement `Identifier()` and `Authenticate()`. To make it available to the access manager, call `RegisterProvider` inside `init` with an initialized provider instance.
```
--------------------------------
### Sync Fork and Create Feature Branch
Source: https://github.com/kittors/clirelay/blob/main/CONTRIBUTING.md
Before starting new work, sync your fork with the latest changes from the 'dev' branch and create a new feature branch from it.
```bash
git fetch origin
git switch -c feature/your-change origin/dev
```
--------------------------------
### Built-in `config-api-key` Provider
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md
Details the built-in API key provider, its credential sources, and configuration example.
```APIDOC
## Built-in `config-api-key` Provider
The proxy includes one built-in access provider:
- `config-api-key`: Validates API keys declared under top-level `api-keys`.
- Credential sources: `Authorization: Bearer`, `X-Goog-Api-Key`, `X-Api-Key`, `?key=`, `?auth_token=`
- Metadata: `Result.Metadata["source"]` is set to the matched source label.
In the CLI server and `sdk/cliproxy`, this provider is registered automatically based on the loaded configuration.
```yaml
api-keys:
- sk-test-123
- sk-prod-456
```
```
--------------------------------
### Register Executor with Core Manager
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-advanced.md
Register the custom executor with the core manager before starting the service. This ensures that requests using the provider key "myprov" are routed to your custom executor.
```go
core := coreauth.NewManager(coreauth.NewFileStore(cfg.AuthDir), nil, nil)
core.RegisterExecutor(myprov.Executor{})
svc, _ := cliproxy.NewBuilder().WithConfig(cfg).WithConfigPath(cfgPath).WithCoreAuthManager(core).Build()
```
--------------------------------
### Initialize and Configure Manager
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md
Construct a new manager and set its providers using globally registered providers. The manager can be nil if no providers are configured.
```go
manager := sdkaccess.NewManager()
manager.SetProviders(sdkaccess.RegisteredProviders())
```
--------------------------------
### Import CLIProxyAPI SDK
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md
Import the necessary packages for using the SDK. Note the /v6 in the module path.
```go
import (
"context"
"errors"
"time"
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
"github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy"
)
```
--------------------------------
### Import SDK Access Package
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md
Import the SDK access package to centralize request authentication logic.
```go
import (
sdkaccess "github.com/router-for-me/CLIProxyAPI/v6/sdk/access"
)
```
--------------------------------
### Manager Lifecycle
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md
Demonstrates how to initialize and configure the access manager with registered providers.
```APIDOC
## Manager Lifecycle
```go
manager := sdkaccess.NewManager()
manager.SetProviders(sdkaccess.RegisteredProviders())
```
- `NewManager` constructs an empty manager.
- `SetProviders` replaces the provider slice using a defensive copy.
- `Providers` retrieves a snapshot that can be iterated safely from other goroutines.
If the manager itself is `nil` or no providers are configured, the call returns `nil, nil`, allowing callers to treat access control as disabled.
```
--------------------------------
### Build CLI Service with Access Manager
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md
Use this snippet to build a CLI service with cliproxy, integrating a pre-configured access manager. Ensure custom providers are registered before building.
```go
coreCfg, _ := config.LoadConfig("config.yaml")
accessManager := sdkaccess.NewManager()
svc, _ := cliproxy.NewBuilder().
WithConfig(coreCfg).
WithConfigPath("config.yaml").
WithRequestAccessManager(accessManager).
Build()
```
--------------------------------
### Clone Repository and Create Feature Branch
Source: https://github.com/kittors/clirelay/blob/main/README.md
Steps to clone the repository, switch to a development branch, and create a new feature branch for contributions.
```bash
git clone https://github.com/kittors/CliRelay.git
cd CliRelay
# 2. Create a feature branch from the latest dev baseline
git fetch origin
git switch -c feature/amazing-feature origin/dev
```
--------------------------------
### Loading Providers from External Go Modules
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md
Explains how to import external Go modules to register their access providers.
```APIDOC
## Loading Providers from External Go Modules
To consume a provider shipped in another Go module, import it for its registration side effect:
```go
import (
_ "github.com/acme/xplatform/sdk/access/providers/partner" // registers partner-token
sdkaccess "github.com/router-for-me/CLIProxyAPI/v6/sdk/access"
)
```
The blank identifier import ensures `init` runs so `sdkaccess.RegisterProvider` executes before you call `RegisteredProviders()` (or before `cliproxy.NewBuilder().Build()`).
```
--------------------------------
### Run Frontend Verification
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
Execute frontend tests for request logs and logs pages using Bun and Vitest. Ensure all tests pass.
```bash
bun vitest run src/modules/monitor/__tests__/RequestLogsPage.test.tsx src/modules/logs/__tests__/LogsPage.test.tsx
```
--------------------------------
### Implement Custom Provider
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md
Implement the Identifier() and Authenticate() methods for a custom provider. Register it using sdkaccess.RegisterProvider within an init function.
```go
type customProvider struct{}
func (p *customProvider) Identifier() string { return "my-provider" }
func (p *customProvider) Authenticate(ctx context.Context, r *http.Request) (*sdkaccess.Result, *sdkaccess.AuthError) {
token := r.Header.Get("X-Custom")
if token == "" {
return nil, sdkaccess.NewNotHandledError()
}
if token != "expected" {
return nil, sdkaccess.NewInvalidCredentialError()
}
return &sdkaccess.Result{
Provider: p.Identifier(),
Principal: "service-user",
Metadata: map[string]string{"source": "x-custom"},
}, nil
}
func init() {
sdkaccess.RegisterProvider("custom", &customProvider{})
}
```
--------------------------------
### Run Go Tests
Source: https://github.com/kittors/clirelay/blob/main/CONTRIBUTING.md
Execute all Go tests in the project. This command should be run before opening or updating a pull request for Go changes.
```bash
go test ./...
```
--------------------------------
### Minimal CLI Proxy Service Embed
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md
Embed the CLI proxy service with minimal configuration. Load configuration, build the service, and run it with a cancellable context. The service handles config watching, token refresh, and graceful shutdown.
```go
cfg, err := config.LoadConfig("config.yaml")
if err != nil { panic(err) }
svc, err := cliproxy.NewBuilder().
WithConfig(cfg).
WithConfigPath("config.yaml"). // absolute or working-dir relative
Build()
if err != nil { panic(err) }
ctx, cancel := context.WithCancel(context.Background())
deferr cancel()
if err := svc.Run(ctx); err != nil && !errors.Is(err, context.Canceled) {
panic(err)
}
```
--------------------------------
### CLI Proxy Service with Server Options
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md
Configure the embedded CLI proxy service with custom server options, including global middleware, engine configuration, custom routes, and request loggers.
```go
svc, _ := cliproxy.NewBuilder().
WithConfig(cfg).
WithConfigPath("config.yaml").
WithServerOptions(
// Add global middleware
cliproxy.WithMiddleware(func(c *gin.Context) { c.Header("X-Embed", "1"); c.Next() }),
// Tweak gin engine early (CORS, trusted proxies, etc.)
cliproxy.WithEngineConfigurator(func(e *gin.Engine) { e.ForwardedByClientIP = true }),
// Add your own routes after defaults
cliproxy.WithRouterConfigurator(func(e *gin.Engine, _ *handlers.BaseAPIHandler, _ *config.Config) {
e.GET("/healthz", func(c *gin.Context) { c.String(200, "ok") })
}),
// Override request log writer/dir
cliproxy.WithRequestLoggerFactory(func(cfg *config.Config, cfgPath string) logging.RequestLogger {
return logging.NewFileRequestLogger(true, "logs", filepath.Dir(cfgPath))
}),
).
Build()
```
--------------------------------
### Use Development Docker Image
Source: https://github.com/kittors/clirelay/blob/main/README.md
To test development builds, set the `channel` to `dev` in the `auto-update` section of `config.yaml`.
```yaml
auto-update:
channel: dev
```
--------------------------------
### Run OpenAI Claude Empty Tool Name Chain Tests
Source: https://github.com/kittors/clirelay/blob/main/docs/internal-review/empty-tool-name-chain-test-report-20260613.md
Executes Go tests for OpenAI and Claude tool name chain scenarios, including empty tool names and non-streaming cases.
```bash
rtk go test ./test -run 'TestOpenAIClaude.*Tool.*Chain|TestOpenAIClaudeEmptyToolNameNonStreamingChain' -count=1 -v
```
--------------------------------
### Run Backend Verification
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
Execute backend tests for usage and management handlers. Ensure all tests pass.
```bash
go test ./internal/usage ./internal/api/handlers/management -count=1
```
--------------------------------
### Enable Redis Persistence
Source: https://github.com/kittors/clirelay/blob/main/README.md
Enable data persistence by setting `redis.enable` to `true` in `config.yaml` and providing your Redis server address.
```yaml
redis:
enable: true
```
--------------------------------
### Register Models with Global Registry
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-advanced.md
Expose custom provider models under `/v1/models` by registering them in the global model registry. This is done using the auth ID (client ID) and provider name.
```go
models := []*cliproxy.ModelInfo{
{ ID: "myprov-pro-1", Object: "model", Type: "myprov", DisplayName: "MyProv Pro 1" },
}
cliproxy.GlobalModelRegistry().RegisterClient(authID, "myprov", models)
```
--------------------------------
### Run OpenAI Compat Executor Claude Tests
Source: https://github.com/kittors/clirelay/blob/main/docs/internal-review/empty-tool-name-chain-test-report-20260613.md
Executes Go tests for the OpenAICompatExecutor with Claude, focusing on empty tool names and various streaming/non-streaming scenarios.
```bash
rtk go test ./internal/runtime/executor -run 'TestOpenAICompatExecutorClaude(StreamSkipsEmptyToolNameEndToEnd|StreamSkipsMissingToolNameArgumentsEndToEnd|StreamPreservesValidParallelToolWhenEmptyIndexFirstEndToEnd|NonStreamSkipsEmptyToolNameEndToEnd)' -count=1 -v
```
--------------------------------
### Run Go Test for Cleanup Function
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
Command to run the specific test for the ClearAllRequestLogs function to verify its behavior. Use the -count=1 flag to ensure the test runs fresh.
```bash
go test ./internal/usage -run TestClearAllRequestLogsRemovesRequestLogTablesOnly -count=1
```
--------------------------------
### Execute Terminal Management UI
Source: https://github.com/kittors/clirelay/blob/main/README.md
Use this command to launch the terminal-first management interface for CliRelay. This provides an alternative to the web-based panel.
```bash
docker compose exec cli-proxy-api ./cli-proxy-api -tui
```
--------------------------------
### Custom Token Client Provider
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md
Replace the default token client loaders with a custom provider, such as one that loads credentials from memory.
```go
type memoryTokenProvider struct{}
func (p *memoryTokenProvider) Load(ctx context.Context, cfg *config.Config) (*cliproxy.TokenClientResult, error) {
// Populate from memory/remote store and return counts
return &cliproxy.TokenClientResult{}, nil
}
svc, _ := cliproxy.NewBuilder().
WithConfig(cfg).
WithConfigPath("config.yaml").
WithTokenClientProvider(&memoryTokenProvider{}).
WithAPIKeyClientProvider(cliproxy.NewAPIKeyClientProvider()).
Build()
```
--------------------------------
### Implement a Provider Executor
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-advanced.md
Implement the `auth.ProviderExecutor` interface to create a custom provider executor. This includes methods for identifying the provider, preparing HTTP requests, executing requests (both streaming and non-streaming), and refreshing authentication tokens.
```go
package myprov
import (
"context"
"net/http"
coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth"
clipexec "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor"
)
type Executor struct{}
func (Executor) Identifier() string { return "myprov" }
// Optional: mutate outbound HTTP requests with credentials
func (Executor) PrepareRequest(req *http.Request, a *coreauth.Auth) error {
// Example: req.Header.Set("Authorization", "Bearer "+a.APIKey)
return nil
}
func (Executor) Execute(ctx context.Context, a *coreauth.Auth, req clipexec.Request, opts clipexec.Options) (clipexec.Response, error) {
// Build HTTP request based on req.Payload (already translated into provider format)
// Use per‑auth transport if provided: transport := a.RoundTripper // via RoundTripperProvider
// Perform call and return provider JSON payload
return clipexec.Response{Payload: []byte(`{"ok":true}`)}, nil
}
func (Executor) ExecuteStream(ctx context.Context, a *coreauth.Auth, req clipexec.Request, opts clipexec.Options) (<-chan clipexec.StreamChunk, error) {
ch := make(chan clipexec.StreamChunk, 1)
go func() { defer close(ch); ch <- clipexec.StreamChunk{Payload: []byte("data: {\"done\":true}\n\n")} }()
return ch, nil
}
func (Executor) Refresh(ctx context.Context, a *coreauth.Auth) (*coreauth.Auth, error) {
// Optionally refresh tokens and return updated auth
return a, nil
}
```
--------------------------------
### Load External Providers
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md
Import external provider modules using a blank identifier to ensure their registration side effect runs before accessing registered providers.
```go
import (
_ "github.com/acme/xplatform/sdk/access/providers/partner" // registers partner-token
sdkaccess "github.com/router-for-me/CLIProxyAPI/v6/sdk/access"
)
```
--------------------------------
### Configure OpenAI Codex Tool
Source: https://github.com/kittors/clirelay/blob/main/README.md
Configure your AI tool, such as OpenAI Codex, to use CliRelay by setting the `base_url` to `http://localhost:8317/v1` in its configuration file.
```toml
[model_providers.tabcode]
name = "openai"
base_url = "http://localhost:8317/v1"
requires_openai_auth = true
```
--------------------------------
### Execute Request with Core Auth Manager
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md
Programmatically execute requests using the core auth manager for non-streaming and streaming responses.
```go
// Non‑streaming
resp, err := core.Execute(ctx, []string{"gemini"}, req, opts)
// Streaming
chunks, err := core.ExecuteStream(ctx, []string{"gemini"}, req, opts)
for ch := range chunks { /* ... */ }
```
--------------------------------
### Provide Custom HTTP Transport
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-advanced.md
Use `Manager.SetRoundTripperProvider` to inject a custom `*http.Transport` that can handle per-authentication logic, such as proxy configurations.
```go
core.SetRoundTripperProvider(myProvider) // returns transport per auth
```
--------------------------------
### Implement ClearAllRequestLogs Function
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
Implements the backend logic for clearing all request logs and their associated content from the database. It uses a transaction to ensure atomicity and includes a VACUUM command to reclaim space.
```go
type ClearRequestLogsResult struct {
DeletedLogs int64 `json:"deleted_logs"`
DeletedContents int64 `json:"deleted_contents"`
}
func ClearAllRequestLogs() (ClearRequestLogsResult, error) {
db := getDB()
if db == nil {
return ClearRequestLogsResult{}, fmt.Errorf("usage: database not initialised")
}
tx, err := db.Begin()
if err != nil {
return ClearRequestLogsResult{}, fmt.Errorf("usage: begin clear request logs: %w", err)
}
defer rollbackTx(tx)
contentResult, err := tx.Exec("DELETE FROM request_log_content")
if err != nil {
return ClearRequestLogsResult{}, fmt.Errorf("usage: clear request_log_content: %w", err)
}
logResult, err := tx.Exec("DELETE FROM request_logs")
if err != nil {
return ClearRequestLogsResult{}, fmt.Errorf("usage: clear request_logs: %w", err)
}
deletedContents, _ := contentResult.RowsAffected()
deletedLogs, _ := logResult.RowsAffected()
if err := tx.Commit(); err != nil {
return ClearRequestLogsResult{}, fmt.Errorf("usage: commit clear request logs: %w", err)
}
if _, err := db.Exec("VACUUM"); err != nil {
log.Warnf("usage: vacuum after request log cleanup failed: %v", err)
}
return ClearRequestLogsResult{
DeletedLogs: deletedLogs,
DeletedContents: deletedContents,
},
nil
}
```
--------------------------------
### Hot Reloading Access Providers
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md
This code demonstrates how to refresh configuration-backed providers and reset the access manager's provider chain for hot reloading. This enables runtime updates without restarting the process.
```go
// configaccess is github.com/router-for-me/CLIProxyAPI/v6/internal/access/config_access
configaccess.Register(&newCfg.SDKConfig)
accessManager.SetProviders(sdkaccess.RegisteredProviders())
```
--------------------------------
### Commit and Push Changes
Source: https://github.com/kittors/clirelay/blob/main/README.md
How to commit your changes and push them to a feature branch for a pull request.
```bash
# 3. Make your changes & commit
git commit -m "feat: add amazing feature"
# 4. Push to your branch & open a PR targeting dev
git push origin feature/amazing-feature
```
--------------------------------
### Commit Backend Changes
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
Command to stage and commit the modified Go files for the request log cleanup feature.
```bash
git add internal/usage/usage_db.go internal/usage/usage_db_test.go
git commit -m "feat: add request log database cleanup helper"
```
--------------------------------
### Authenticate Requests
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md
Authenticate incoming requests using the manager. Handle success, no credentials, invalid credentials, or internal/transport failures.
```go
result, authErr := manager.Authenticate(ctx, req)
switch {
case authErr == nil:
// Authentication succeeded; result describes the provider and principal.
case sdkaccess.IsAuthErrorCode(authErr, sdkaccess.AuthErrorCodeNoCredentials):
// No recognizable credentials were supplied.
case sdkaccess.IsAuthErrorCode(authErr, sdkaccess.AuthErrorCodeInvalidCredential):
// Supplied credentials were present but rejected.
default:
// Internal/transport failure was returned by a provider.
}
```
--------------------------------
### Custom Core Auth Manager
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md
Provide a custom core authentication manager to customize transports or hooks. Implement a custom http.RoundTripper for per-auth proxy settings.
```go
core := coreauth.NewManager(coreauth.NewFileStore(cfg.AuthDir), nil, nil)
core.SetRoundTripperProvider(myRTProvider) // per‑auth *http.Transport
svc, _ := cliproxy.NewBuilder().
WithConfig(cfg).
WithConfigPath("config.yaml").
WithCoreAuthManager(core).
Build()
```
```go
type myRTProvider struct{}
func (myRTProvider) RoundTripperFor(a *coreauth.Auth) http.RoundTripper {
if a == nil || a.ProxyURL == "" { return nil }
u, _ := url.Parse(a.ProxyURL)
return &http.Transport{ Proxy: http.ProxyURL(u) }
}
```
--------------------------------
### Access Management Panel
Source: https://github.com/kittors/clirelay/blob/main/README.md
Open this URL in your browser to access the CliRelay management panel. Ensure the control panel is enabled in your configuration.
```bash
http://localhost:8317/manage
```
--------------------------------
### Authenticating Requests
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md
Shows how to authenticate requests using the manager and handle different authentication outcomes.
```APIDOC
## Authenticating Requests
```go
result, authErr := manager.Authenticate(ctx, req)
switch {
case authErr == nil:
// Authentication succeeded; result describes the provider and principal.
case sdkaccess.IsAuthErrorCode(authErr, sdkaccess.AuthErrorCodeNoCredentials):
// No recognizable credentials were supplied.
case sdkaccess.IsAuthErrorCode(authErr, sdkaccess.AuthErrorCodeInvalidCredential):
// Supplied credentials were present but rejected.
default:
// Internal/transport failure was returned by a provider.
}
```
`Manager.Authenticate` walks the configured providers in order. It returns on the first success, skips providers that return `AuthErrorCodeNotHandled`, and aggregates `AuthErrorCodeNoCredentials` / `AuthErrorCodeInvalidCredential` for a final result.
Each `Result` includes the provider identifier, the resolved principal, and optional metadata (for example, which header carried the credential).
```
--------------------------------
### Define Management API Route for Request Log Cleanup
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
This line of code registers a DELETE route at `/usage/logs` that maps to the `DeleteUsageLogs` handler in the management API.
```go
mgmt.DELETE("/usage/logs", s.mgmt.DeleteUsageLogs)
```
--------------------------------
### Configure Request Log Storage
Source: https://github.com/kittors/clirelay/blob/main/README.md
Tune `request-log-storage` in `config.yaml` to control how request/response bodies are retained. Options include retention days, content storage, and maximum size.
```yaml
request-log-storage:
content-retention-days: 0
store-content: false
max-total-size-mb: 1024
```
--------------------------------
### Register Request and Response Translators
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-advanced.md
Register translation functions in the `sdk/translator` registry to convert between inbound and provider-specific schemas. This supports new provider formats by defining how to translate requests and responses.
```go
package myprov
import (
"context"
sdktr "github.com/router-for-me/CLIProxyAPI/v6/sdk/translator"
)
const (
FOpenAI = sdktr.Format("openai.chat")
FMyProv = sdktr.Format("myprov.chat")
)
func init() {
sdktr.Register(FOpenAI, FMyProv,
// Request transform (model, rawJSON, stream)
func(model string, raw []byte, stream bool) []byte { return convertOpenAIToMyProv(model, raw, stream) },
// Response transform (stream & non‑stream)
sdktr.ResponseTransform{
Stream: func(ctx context.Context, model string, originalReq, translatedReq, raw []byte, param *any) []string {
return convertStreamMyProvToOpenAI(model, originalReq, translatedReq, raw)
},
NonStream: func(ctx context.Context, model string, originalReq, translatedReq, raw []byte, param *any) string {
return convertMyProvToOpenAI(model, originalReq, translatedReq, raw)
},
},
)
}
```
--------------------------------
### Test ClearAllRequestLogsRemovesRequestLogTablesOnly
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
Tests that the ClearAllRequestLogs function correctly removes only the request log tables and their content. It initializes the database, inserts log data, calls the cleanup function, and verifies that the tables are empty.
```go
func TestClearAllRequestLogsRemovesRequestLogTablesOnly(t *testing.T) {
dbPath := t.TempDir() + "/usage.db"
if err := InitDB(dbPath); err != nil {
t.Fatalf("InitDB() error = %v", err)
}
defer CloseDB()
entry := LogEntry{
Timestamp: time.Now().UTC(),
APIKey: "sk-test",
Model: "gpt-5",
TotalTokens: 12,
}
logID, err := InsertLog(entry)
if err != nil {
t.Fatalf("InsertLog() error = %v", err)
}
if _, err := getDB().Exec(
`INSERT INTO request_log_content (log_id, timestamp, compression, input_content, output_content)
VALUES (?, ?, 'none', X'01', X'02')`,
logID,
time.Now().UTC().Format(time.RFC3339),
); err != nil {
t.Fatalf("seed request_log_content error = %v", err)
}
result, err := ClearAllRequestLogs()
if err != nil {
t.Fatalf("ClearAllRequestLogs() error = %v", err)
}
if result.DeletedLogs != 1 || result.DeletedContents != 1 {
t.Fatalf("unexpected cleanup result: %#v", result)
}
var logsCount, contentCount int
if err := getDB().QueryRow("SELECT COUNT(*) FROM request_logs").Scan(&logsCount); err != nil {
t.Fatalf("count request_logs error = %v", err)
}
if err := getDB().QueryRow("SELECT COUNT(*) FROM request_log_content").Scan(&contentCount); err != nil {
t.Fatalf("count request_log_content error = %v", err)
}
if logsCount != 0 || contentCount != 0 {
t.Fatalf("expected empty request log tables, got logs=%d content=%d", logsCount, contentCount)
}
}
```
--------------------------------
### Management Endpoint for Clearing Request Logs
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/specs/2026-05-08-request-log-database-cleanup-design.md
This is the backend API endpoint definition for initiating the request log cleanup.
```go
DELETE /v0/management/usage/logs
```
--------------------------------
### Commit Changes for Request Log Cleanup Feature
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
This bash script shows the commands to stage and commit the files modified for the request log cleanup feature, including backend, frontend, and test files.
```bash
git add internal/api/handlers/management/usage_logs_handler.go internal/api/handlers/management/usage_logs_handler_test.go internal/api/server.go
git commit -m "feat: expose request log cleanup management endpoint"
```
--------------------------------
### Manual Shutdown of CLI Proxy Service
Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md
Manually shut down the CLI proxy service using a context with a timeout. Cancelling the parent context is the default method.
```go
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
deferr cancel()
_ = svc.Shutdown(ctx)
```
--------------------------------
### Implement Management API Handler for Request Log Cleanup
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
This Go handler function, `DeleteUsageLogs`, is responsible for clearing all request logs from the database. It calls the `ClearAllRequestLogs` function and returns the result or an error.
```go
func (h *Handler) DeleteUsageLogs(c *gin.Context) {
result, err := usage.ClearAllRequestLogs()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
```
--------------------------------
### Add Frontend UI Components for Request Log Cleanup Confirmation
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
This React JSX code renders a button to initiate the log cleanup and a confirmation modal. The modal requires user confirmation before proceeding with the cleanup action.
```typescript
setConfirmClearOpen(false)}
onConfirm={() => {
setConfirmClearOpen(false);
void handleClearDatabaseLogs();
}}
/>
```
--------------------------------
### Merge Feature Branch into Local Dev
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
Merge the 'clear-request-log-db' feature branch into the local 'dev' branch using a fast-forward merge, then push the changes.
```bash
git checkout dev
git merge --ff-only feature/issue-159-clear-request-log-db
git push origin dev
```
--------------------------------
### CliRelay Project Architecture
Source: https://github.com/kittors/clirelay/blob/main/README.md
This tree represents the directory structure of the CliRelay project, detailing the purpose of each major directory.
```text
CliRelay/
├── cmd/server/ # Binary entry point and CLI mode dispatch
├── internal/api/ # HTTP server, management routes, middleware
├── internal/auth/ # Provider OAuth / cookie / browser auth flows
├── internal/config/ # Config parsing, defaults, migrations
├── internal/store/ # Local, Git, PostgreSQL, object-store auth/config persistence
├── internal/tui/ # Terminal management UI
├── internal/usage/ # SQLite usage DB, retention, analytics
├── internal/managementasset/ # /manage panel hosting and asset sync
├── sdk/ # Reusable Go SDK, handlers, executors
├── auths/ # Local credential storage
├── examples/ # SDK / custom provider examples
├── docs/ # Local docs and panel screenshots
└── docker-compose.yml # Container deployment entry
```
--------------------------------
### Implement Frontend API Client for Request Log Cleanup
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
This TypeScript function `clearUsageLogs` makes a DELETE request to the `/usage/logs` endpoint using the `apiClient` to clear request logs.
```typescript
async clearUsageLogs(): Promise<{ deleted_logs: number; deleted_contents: number }> {
return apiClient.delete("/usage/logs");
}
```
--------------------------------
### Frontend API Call for Clearing Usage Logs
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/specs/2026-05-08-request-log-database-cleanup-design.md
This is the frontend JavaScript method used to call the backend API for clearing usage logs.
```typescript
usageApi.clearUsageLogs()
```
--------------------------------
### Write Failing Frontend Test for Request Log Cleanup
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
This test verifies that the frontend correctly triggers the request log cleanup action after user confirmation. It mocks API calls and checks for the expected UI state changes.
```typescript
test("clears request-log database after confirmation", async () => {
const user = userEvent.setup();
mocks.getUsageLogs
.mockResolvedValueOnce({
items: [seedRow],
total: 1,
page: 1,
size: 50,
filters: { api_keys: [], api_key_names: {}, models: [], channels: [] },
stats: { total: 1, success_rate: 100, total_tokens: 30, total_cost: 0.01 },
})
.mockResolvedValueOnce({
items: [],
total: 0,
page: 1,
size: 50,
filters: { api_keys: [], api_key_names: {}, models: [], channels: [] },
stats: { total: 0, success_rate: 0, total_tokens: 0, total_cost: 0 },
});
mocks.clearUsageLogs.mockResolvedValue({ deleted_logs: 1, deleted_contents: 1 });
renderRequestLogsPage();
await user.click(await screen.findByRole("button", { name: /Clear Database Logs/i }));
await user.click(await screen.findByRole("button", { name: /Clear/i }));
await waitFor(() => expect(mocks.clearUsageLogs).toHaveBeenCalledTimes(1));
expect(await screen.findByText("No Data")).toBeInTheDocument();
});
```
--------------------------------
### Write Failing Handler Test for Request Log Cleanup
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
This test verifies the expected behavior of the `DeleteUsageLogs` handler before it is implemented. It checks the HTTP status code and response body for a successful deletion.
```go
func TestDeleteUsageLogsClearsRequestLogDatabase(t *testing.T) {
h := newTestManagementHandler(t)
seedUsageLog(t)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodDelete, "/usage/logs", nil)
h.DeleteUsageLogs(c)
if w.Code != http.StatusOK {
t.Fatalf("status = %d, want %d", w.Code, http.StatusOK)
}
if !strings.Contains(w.Body.String(), `"deleted_logs":1`) {
t.Fatalf("body = %s, want deleted count", w.Body.String())
}
}
```
--------------------------------
### Check Repository Status
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md
Verify the Git repository status to ensure no unrelated changes are present in the feature branch.
```bash
git status --short
```
--------------------------------
### Frontend Component for Request Logs Page
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/specs/2026-05-08-request-log-database-cleanup-design.md
This React component is responsible for rendering the Request Logs page, including the button to trigger the cleanup action.
```typescript
src/modules/monitor/RequestLogsPage.tsx
```
--------------------------------
### Usage-layer Helper for Clearing Request Logs
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/specs/2026-05-08-request-log-database-cleanup-design.md
This Go function clears request log tables within a transaction and optionally runs a VACUUM. It returns the count of deleted rows.
```go
func ClearAllRequestLogs() (ClearRequestLogsResult, error) {
// ... implementation details ...
}
```
--------------------------------
### Suggested Response Shape for Log Cleanup
Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/specs/2026-05-08-request-log-database-cleanup-design.md
This JSON structure represents the expected response from the log cleanup API, indicating the number of deleted items.
```json
{
"deleted_logs": 12345,
"deleted_contents": 12345
}
```
--------------------------------
### Disable Automatic Update Checks
Source: https://github.com/kittors/clirelay/blob/main/README.md
Configure CliRelay to disable automatic update prompts by setting `enabled` to `false` in the `auto-update` section of `config.yaml`.
```yaml
auto-update:
enabled: false
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.