Skip to main content

Config Files

Routerly stores all configuration as JSON files. The exact location depends on the installation scope chosen at install time. Files are written atomically and are human-readable.

The service reads the root directory from the ROUTERLY_HOME environment variable (set automatically by the installer in the daemon unit). If the variable is not set, it falls back to ~/.routerly/.

Directory Layout

User scope (default)

Everything lives under the installing user's home directory.

~/.routerly/
├── app/ # Service binary (managed by installer)
├── config/
│ ├── settings.json # Global settings
│ ├── models.json # Registered LLM models
│ ├── projects.json # Projects, routing, budgets, tokens
│ ├── users.json # User accounts
│ ├── roles.json # Custom roles and permissions
│ └── secret # JWT signing key (mode 0600, keep safe)
└── data/
└── usage.json # Usage records

System scope

Service config and data move to a system-wide directory; the CLI auth tokens remain per-user.

PlatformService config & data directory
Linux/var/lib/routerly/
macOS/Library/Application Support/Routerly/
WindowsC:\ProgramData\Routerly\
/var/lib/routerly/          # (Linux example; see table above for other platforms)
├── config/
│ ├── settings.json
│ ├── models.json
│ ├── projects.json
│ ├── users.json
│ ├── roles.json
│ └── secret # JWT signing key (mode 0600)
└── data/
└── usage.json

CLI auth tokens (always per-user)

Regardless of install scope, each user's CLI credentials are stored in their own home directory, never in the system directory:

~/.routerly/
└── cli/
└── config.json # Saved accounts, JWT tokens, refresh tokens (mode 0600)

settings.json

Global service configuration.

{
"port": 3000,
"host": "0.0.0.0",
"dashboardEnabled": true,
"defaultTimeoutMs": 30000,
"logLevel": "info",
"publicUrl": "http://localhost:3000",
"notifications": []
}
FieldTypeDefaultDescription
portnumber3000TCP port the service listens on
hoststring"0.0.0.0"Bind address. Use 127.0.0.1 behind a reverse proxy
dashboardEnabledbooleantrueEnable or disable the web dashboard
defaultTimeoutMsnumber30000Default provider request timeout in milliseconds
logLevelstring"info"Log verbosity: "error", "warn", "info", "debug"
publicUrlstring"http://localhost:3000"Externally reachable URL, used for notification links
notificationsarray[]Notification channel configurations — see Notifications

models.json

Array of registered LLM model configurations.

[
{
"id": "gpt-5-mini",
"provider": "openai",
"apiKey": "ENCRYPTED:...",
"inputPrice": 0.00015,
"outputPrice": 0.0006,
"cachePrice": 0.000075,
"contextWindow": 128000,
"capabilities": ["chat", "vision"],
"enabled": true
}
]
FieldTypeDescription
idstringUnique model identifier within Routerly
providerstringProvider name: openai, anthropic, gemini, mistral, cohere, xai, ollama, custom
apiKeystringAPI key — stored AES-256 encrypted with the value from secret
inputPricenumberCost per 1,000 input tokens in USD
outputPricenumberCost per 1,000 output tokens in USD
cachePricenumberCost per 1,000 cached/read tokens in USD (optional)
contextWindownumberMaximum context window in tokens
capabilitiesstring[]Supported capabilities: "chat", "vision", "tools", "json_mode"
pricingTiersarrayVolume-based pricing tiers (optional)
enabledbooleanWhether the model is available for routing
baseUrlstringCustom base URL — required for custom provider, used for non-default Ollama hosts
caution

Never edit apiKey values manually. Use the dashboard or CLI to manage API keys; they are encrypted using the secret file.


projects.json

Array of project configurations including routing policies, budgets, tokens, and members.

[
{
"id": "proj_abc123",
"name": "My App",
"slug": "my-app",
"defaultTimeoutMs": 30000,
"policies": ["random"],
"models": ["gpt-5-mini", "claude-haiku-4-5"],
"tokens": [
{
"id": "tok_xyz",
"token": "HASHED:...",
"description": "Production token",
"createdAt": "2024-01-15T10:00:00Z"
}
],
"members": [
{ "userId": "usr_abc", "role": "admin" }
],
"budgets": [
{
"metric": "cost",
"limit": 10.00,
"windowType": "period",
"windowSize": "monthly",
"onExhausted": "block"
}
]
}
]

Project Fields

FieldTypeDescription
idstringInternal project ID (proj_…)
namestringHuman-readable project name
slugstringURL-safe identifier, used in scoped proxy path /projects/{slug}/v1/*
defaultTimeoutMsnumberPer-project request timeout override
policiesstring[]Routing policies in priority order
modelsstring[]Model IDs assigned to the project

Token Fields

FieldTypeDescription
idstringToken ID (tok_…)
tokenstringToken value, stored as a bcrypt hash — the plain sk-rt-… value is only shown once on creation
descriptionstringOptional label
createdAtstringISO 8601 creation timestamp

Budget Fields

FieldTypeDescription
metricstring"cost", "calls", "input_tokens", "output_tokens", "total_tokens"
limitnumberMaximum allowed value for the metric
windowTypestring"period" (fixed calendar window) or "rolling" (sliding window)
windowSizestringFor period: "hourly", "daily", "weekly", "monthly", "yearly". For rolling: "second", "minute", "hour", "day", "week", "month"
onExhaustedstring"block" — return HTTP 503 when budget is reached

users.json

Array of user accounts.

[
{
"id": "usr_abc123",
"email": "admin@example.com",
"passwordHash": "$2b$10$...",
"role": "admin",
"createdAt": "2024-01-01T00:00:00Z"
}
]
FieldTypeDescription
idstringUser ID (usr_…)
emailstringLogin email
passwordHashstringbcrypt hash of the password
rolestringGlobal role name: "admin", "member", "viewer", or a custom role
createdAtstringISO 8601 creation timestamp

roles.json

Array of custom role definitions. The three built-in roles (admin, member, viewer) are not stored here and cannot be modified.

[
{
"name": "billing-viewer",
"permissions": ["usage:read"]
}
]
FieldTypeDescription
namestringUnique role name
permissionsstring[]List of permission strings

Available permissions: models:write, projects:write, users:write, roles:write, settings:write, usage:read, proxy:use.


data/usage.json

Array of usage records, one per LLM request. Written by the service after each completed call.

[
{
"id": "use_abc123",
"timestamp": "2024-01-15T10:30:00Z",
"projectId": "proj_abc",
"projectSlug": "my-app",
"modelId": "gpt-5-mini",
"provider": "openai",
"inputTokens": 150,
"outputTokens": 42,
"cacheTokens": 0,
"totalTokens": 192,
"cost": 0.000048,
"durationMs": 1234,
"status": "success",
"traceId": "trc_xyz"
}
]

This file grows continuously. Routerly does not currently rotate or archive it automatically — back it up and truncate as needed.


secret

A single-line file containing the 32-byte AES-256 encryption key used to encrypt API keys in models.json.

a1b2c3d4e5f6...

Never share or commit this file. If lost, all stored API keys must be re-entered.