Complete command-line interface guide for administering the Authly OAuth 2.1 + OpenID Connect 1.0 authorization server.
CLI Access: python -m authly
Admin Commands: python -m authly admin
Architecture: API-first (CLI uses HTTP API exclusively)
Resource Mode: Unified resource manager with AUTHLY_MODE=cli for optimal performance
๐ก Virtual Environment Usage
- With
uv run: Automatically sources the virtual environment (.venv/bin/activate) - recommended for simplicity- Manual activation: Run
source .venv/bin/activatefirst, then usepython -m authlycommands directly- All examples in this guide use
uv runfor consistency and ease of use
# Install Authly (all groups including test/dev with forced update)
uv sync --all-groups -U
# Start Authly server (embedded development mode)
uv run python -m authly serve --embedded
# In another terminal, access admin CLI
uv run python -m authly admin --help# Login to admin interface
uv run python -m authly admin auth login
# Enter admin credentials when prompted
# Create your first OAuth client
uv run python -m authly admin client create \
--name "My Application" \
--type confidential \
--redirect-uri "https://myapp.com/callback"
# Create a scope
uv run python -m authly admin scope create \
--name "read" \
--description "Read access to user data"
# Check system status
uv run python -m authly admin status
# Show configuration and paths
uv run python -m authly admin auth infopython -m authly [OPTIONS] COMMAND [ARGS]...
Commands:
admin Administrative operations for Authly
serve Start the Authly web service--version Show version and exit
--commands Show all available commands and options in a tree view
--install-completion Install shell tab completion for your shell
--help Show help message and exitThe CLI supports tab completion for faster command entry:
# Install tab completion for your shell (bash/zsh/fish)
python -m authly --install-completion
# After installation, restart your shell or source the completion
source ~/.bashrc # for bash
# Now you can use TAB to complete commands
python -m authly [TAB] # Shows: admin serve
python -m authly admin [TAB] # Shows: auth client scope status
python -m authly admin client [TAB] # Shows: create list show update delete regenerate-secretView all available commands and options in a structured tree format:
# Display complete command tree with descriptions
python -m authly --commands
# Example output:
authly
โโโ admin # Administrative operations for Authly.
โ โโโ auth # Authentication commands for admin access.
โ โ โโโ login # Login to the Authly Admin API.
โ โ โโโ logout # Logout from the Authly Admin API.
โ โ โโโ ...
โ โโโ client # Manage OAuth 2.1 clients.
โ โ โโโ create # Create a new OAuth 2.1 client.
โ โ โโโ list # List all OAuth clients.
โ โ โโโ ...
โโโ serve # Start the Authly web service.The CLI provides contextual help with examples for every command:
# Get help for any command
python -m authly admin --help # Main admin help
python -m authly admin client --help # Client commands help
python -m authly admin client create --help # Specific command help
# Help includes:
# - Command descriptions
# - Available options with types
# - Practical examples
# - Security notes
# - Exit codesExample Help Output:
$ python -m authly admin client create --help
Usage: python -m authly admin client create [OPTIONS]
Create a new OAuth 2.1 client.
Creates an OAuth client application that can request authorization.
Public clients (SPAs, mobile) don't receive a secret.
Confidential clients (backend) receive a client secret.
Examples:
# Create a public client for a React SPA
$ authly client create --name "My React App" --type public \
--redirect-uri "http://localhost:3000/callback"
# Create a confidential client for a backend API
$ authly client create --name "Backend Service" --type confidential \
--redirect-uri "https://api.example.com/oauth/callback" \
--scope "read write admin"
Options:
--name TEXT Client name [required]
--type [public|confidential] Client type [required]
--redirect-uri TEXT Redirect URI (can be specified multiple times) [required]
--scope TEXT Default scopes (space-separated)
--help Show this message and exit.The Authly CLI uses a unified resource manager architecture that automatically optimizes for administrative operations:
# CLI mode automatically configured when running admin commands
AUTHLY_MODE=cli python -m authly admin statusCLI Mode Characteristics:
| Feature | CLI Mode | Production Mode | Embedded Mode |
|---|---|---|---|
| Pool Size | 1-3 connections | 5-20 connections | 2-8 connections |
| Timeout | 10s | 30s | 15s |
| Idle Time | 1 minute | 5 minutes | 3 minutes |
| Bootstrap | Disabled | Environment controlled | Always enabled |
| Lifecycle | Context-managed | FastAPI lifespan | Self-contained |
CLI mode provides several optimizations for administrative workflows:
- Minimal Resource Usage: Small connection pool optimized for short operations
- Fast Cleanup: Resources automatically cleaned up after each command
- No Bootstrap Overhead: Skips admin bootstrap (assumes existing setup)
- Quick Timeouts: Optimized for interactive CLI usage
The CLI automatically detects and sets optimal resource mode:
# Automatic CLI mode (recommended)
python -m authly admin client list
# Manual override (advanced usage)
AUTHLY_MODE=production python -m authly admin status # Uses production settings
AUTHLY_MODE=testing python -m authly admin status # Uses testing settingsMode Aliases Supported:
cli,adminโ CLI modeproduction,prodโ Production modeembedded,embed,dev,developmentโ Embedded modetesting,testโ Testing mode
CLI mode uses context-managed database connections:
# Simplified connection lifecycle for CLI operations
async with resource_manager.get_database().connection() as conn:
# Execute admin operation
result = await admin_operation(conn)
# Connection automatically cleaned upConnection Pool Settings (CLI Mode):
{
"min_size": 1, # Minimal baseline
"max_size": 3, # Small pool for CLI ops
"timeout": 10.0, # Quick connection timeout
"max_idle": 60.0, # 1 minute idle timeout
"reconnect_timeout": 1.0 # Fast reconnection
}Start the Authly web service.
Options:
--host TEXT Host to bind to (default: 0.0.0.0)
--port INTEGER Port to bind to (default: 8000)
--workers INTEGER Number of worker processes (default: 1)
--embedded Run with embedded PostgreSQL container
--seed Seed test data (only with --embedded)
--log-level TEXT Logging level (default: info)
--access-log / --no-access-log Enable/disable access logging (default: enabled)Examples:
# Production server
python -m authly serve --host 0.0.0.0 --port 8000
# Development with embedded database
python -m authly serve --embedded
# Development with embedded database and test data
python -m authly serve --embedded --seed
# Multi-worker production
python -m authly serve --workers 4
# Custom logging
python -m authly serve --log-level debug --no-access-logEnvironment Variables:
# Resource Mode (automatically optimizes for CLI usage)
AUTHLY_MODE="cli"
# Database Configuration
DATABASE_URL="postgresql://user:pass@host:5432/authly"
# JWT Configuration
JWT_SECRET_KEY="your-secret-key"
JWT_REFRESH_SECRET_KEY="your-refresh-secret"
# Admin API Configuration (for CLI communication)
AUTHLY_ADMIN_API_ENABLED="true"All admin commands use the format: python -m authly admin COMMAND
The admin commands are delegated to the unified admin CLI implementation, ensuring consistency across all access methods.
Authenticate with the Authly admin API.
Interactive Login:
$ python -m authly admin auth login
Username: admin
Password: [hidden]
โ Successfully logged in as admin
Token stored securely in ~/.authly/tokens.jsonOptions:
--username TEXT Admin username
--password TEXT Admin password (not recommended for security)
--api-url TEXT Admin API URL (default: auto-detect)
--show-token Display the access and refresh tokens (use with caution)Examples:
# Interactive login (recommended)
python -m authly admin auth login
# Non-interactive (CI/CD environments only)
python -m authly admin auth login --username admin --password "$ADMIN_PASSWORD"
# Custom API URL
python -m authly admin auth login --api-url "https://auth.mycompany.com"
# Show tokens for debugging (careful - tokens are sensitive!)
python -m authly admin auth login --show-token
โ Successfully logged in as admin
Access token: eyJhbGciOiJIUzI1NiIs...
Refresh token: eyJhbGciOiJIUzI1NiIs...Logout from the admin API and clear stored tokens.
$ python -m authly admin auth logout
โ Successfully logged out
Tokens cleared from ~/.authly/tokens.jsonShow current authentication status.
$ python -m authly admin auth whoami
โ Authenticated as: admin
โ Token expires: 2025-07-30 15:30:00 UTC
โ Scopes: admin:clients:read, admin:clients:write, admin:scopes:read, admin:scopes:writeRefresh authentication tokens.
$ python -m authly admin auth refresh
โ Token refreshed successfully
New expiration: 2025-07-30 16:30:00 UTC
Token verified - authentication activeShow Authly configuration and internal information.
$ python -m authly admin auth info
Authly Configuration Information
==================================================
Configuration directory: /home/user/.authly
Token file: /home/user/.authly/tokens.json
Token file exists: True
API Configuration:
API URL: http://localhost:8000
Admin API enabled: true
Environment:
AUTHLY_MODE: cli
DATABASE_URL: set
JWT_SECRET_KEY: set
JWT_REFRESH_SECRET_KEY: set
Version Information:
Authly version: 0.5.8
Authentication Status:
Status: Authenticated
Token expires: 2025-07-30 15:30:00 UTCShows:
- Configuration directory location (
.authlyfolder) - Token file path and existence
- API endpoint configuration
- Environment variable status
- Authly version
- Current authentication status
Show authentication and API status.
$ python -m authly admin auth status
โ API Health: healthy
API URL: http://localhost:8000
โ Authentication: Logged in
Database: Connected
OAuth clients: 2
OAuth scopes: 17Options:
--verbose, -v Show detailed token informationExamples:
# Basic auth status
python -m authly admin auth status
# Detailed auth status with token info
python -m authly admin auth status --verboseAll authentication commands are also available through the auth subgroup for organized access:
Available Commands:
login Login to the Authly Admin API
logout Logout from the Authly Admin API
whoami Show current authentication status
status Show authentication and API status
refresh Refresh authentication tokens
info Show Authly configuration and internal informationExamples:
# Authentication commands are accessed through the auth group:
python -m authly admin auth login # Login to the admin API
python -m authly admin auth logout # Logout and clear tokens
python -m authly admin auth whoami # Show authentication status
python -m authly admin auth status # Authentication and API status
python -m authly admin auth refresh # Refresh authentication tokens
python -m authly admin auth info # Show configuration informationCreate a new OAuth 2.1 client.
Required Options:
--name TEXT Client display name
--type [confidential|public] Client type
--redirect-uri TEXT Redirect URI (can be used multiple times)Optional Options:
--scope TEXT Assign scope to client (can be used multiple times)
--client-uri TEXT Client homepage URL
--logo-uri TEXT Client logo URL
--tos-uri TEXT Terms of service URL
--policy-uri TEXT Privacy policy URL
--contacts TEXT Contact email (can be used multiple times)Examples:
# Basic confidential client
python -m authly admin client create \
--name "My Web App" \
--type confidential \
--redirect-uri "https://myapp.com/callback"
# Public client with multiple redirect URIs
python -m authly admin client create \
--name "My Mobile App" \
--type public \
--redirect-uri "myapp://callback" \
--redirect-uri "http://localhost:3000/callback"
# Client with metadata and scopes
python -m authly admin client create \
--name "Enterprise App" \
--type confidential \
--redirect-uri "https://enterprise.com/oauth/callback" \
--scope "read" \
--scope "write" \
--client-uri "https://enterprise.com" \
--contacts "admin@enterprise.com"Success Output:
โ Client created successfully
Client ID: 7f9a8b2c-1234-5678-9abc-def012345678
Client Secret: cs_1a2b3c4d5e6f7g8h9i0j...
Name: My Web App
Type: confidential
Redirect URIs: https://myapp.com/callback
Scopes: read, write
Status: active
โ ๏ธ Save the client secret securely - it cannot be retrieved again!List OAuth clients.
Options:
--limit INTEGER Number of clients to show (default: 20)
--offset INTEGER Pagination offset (default: 0)
--show-inactive Include inactive clients
--output [table|json] Output format (default: table)Examples:
# List active clients
python -m authly admin client list
# Show all clients including inactive
python -m authly admin client list --show-inactive
# JSON output for scripting
python -m authly admin client list --output json
# Paginated listing
python -m authly admin client list --limit 10 --offset 20Table Output:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโ
โ Client ID โ Name โ Type โ Status โ Created โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโค
โ 7f9a8b2c-1234-5678-9abc-def012345678 โ My Web App โ confidential โ active โ 2025-07-10 10:00:00 โ
โ 8e8b7a1d-5678-9012-cdef-345678901234 โ My Mobile App โ public โ active โ 2025-07-10 11:00:00 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโ
Total: 2 clientsCreate a new OAuth scope.
Required Options:
--name TEXT Scope name (e.g., 'read', 'write', 'profile')
--description TEXT Human-readable descriptionOptional Options:
--default Make this a default scope (assigned automatically)Examples:
# Basic scope
python -m authly admin scope create \
--name "read" \
--description "Read access to user data"
# Default scope
python -m authly admin scope create \
--name "profile" \
--description "Access to user profile information" \
--defaultList OAuth scopes.
Options:
--show-inactive Include inactive scopes
--output [table|json] Output format (default: table)Examples:
# List active scopes
python -m authly admin scope list
# Include inactive scopes
python -m authly admin scope list --show-inactive
# JSON output
python -m authly admin scope list --output jsonOutput:
โโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโ
โ Name โ Description โ Default โ Status โ Created โ
โโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโค
โ read โ Read access to user data โ No โ active โ 2025-07-10 10:00:00 โ
โ write โ Write access to user data โ No โ active โ 2025-07-10 10:30:00 โ
โ profile โ Access to user profile info โ Yes โ active โ 2025-07-10 11:00:00 โ
โโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโ
Total: 3 scopes (2 active, 1 default)Show system status and configuration.
Options:
--output [table|json] Output format (default: table)
--verbose Show detailed informationExamples:
# Basic status
python -m authly admin status
# Verbose status with details
python -m authly admin status --verbose
# JSON output for monitoring
python -m authly admin status --output jsonOutput:
Authly System Status
๐ข System Health: Healthy
๐ Version: 1.0.0
โฑ๏ธ Uptime: 2 days, 5 hours, 30 minutes
Database:
Status: Connected
Pool Size: 10
Active Connections: 3
OAuth Metrics:
Active Clients: 5
Total Scopes: 8
Active Tokens: 127
Admin API:
Status: Enabled
URL: http://localhost:8000
Rate Limit: 60 requests/minute
Last Updated: 2025-07-10 12:00:00 UTCThe CLI uses Authly's unified resource manager architecture with optimal settings for admin operations:
# Resource Mode - Automatically optimizes for CLI usage
AUTHLY_MODE="cli" # Triggers CLI-optimized resource managementCLI Mode Features:
- Minimal Database Pool: 1-3 connections optimized for short-lived operations
- Context-Managed Lifecycle: Resources cleaned up after each command
- No Bootstrap: Assumes existing admin system setup
- Fast Timeout: 10s timeout, 1min idle for quick operations
The CLI respects these environment variables:
# Resource Management
AUTHLY_MODE="cli" # Enables CLI-optimized resource management
# Database Configuration
DATABASE_URL="postgresql://user:pass@host:5432/authly"
# JWT Configuration
JWT_SECRET_KEY="your-secret-key"
JWT_REFRESH_SECRET_KEY="your-refresh-secret"
# Admin API Configuration
AUTHLY_ADMIN_API_ENABLED="true"
AUTHLY_ADMIN_API_URL="http://localhost:8000"
# Development & Debugging
AUTHLY_DEV_MODE="true"
AUTHLY_LOG_LEVEL="DEBUG"The CLI automatically sets AUTHLY_MODE=cli when running admin commands:
# These commands automatically use CLI mode
python -m authly admin auth login
python -m authly admin client list
python -m authly admin status
# Manual mode override (advanced usage)
AUTHLY_MODE=production python -m authly admin statusCreate ~/.authly/config.toml for persistent CLI settings:
[api]
url = "https://auth.mycompany.com"
timeout = 30
[auth]
auto_refresh = true
token_file = "~/.authly/tokens.json"
[output]
default_format = "table"
show_timestamps = trueAdmin tokens are securely stored in ~/.authly/tokens.json:
{
"access_token": "encrypted_token_here",
"refresh_token": "encrypted_refresh_token",
"expires_at": "2025-07-10T15:30:00Z",
"api_url": "http://localhost:8000"
}Security Features:
- Tokens are encrypted using system keyring when available
- File permissions set to 600 (owner read/write only)
- Automatic token refresh before expiration
- Secure cleanup on logout
Complete workflow for registering a new application:
# 1. Login as admin
uv run python -m authly admin auth login
# 2. Create necessary scopes
uv run python -m authly admin scope create \
--name "user:read" \
--description "Read user information"
uv run python -m authly admin scope create \
--name "user:write" \
--description "Modify user information"
# 3. Create the OAuth client
uv run python -m authly admin client create \
--name "Customer Portal" \
--type confidential \
--redirect-uri "https://portal.example.com/auth/callback" \
--redirect-uri "https://portal.example.com/auth/silent-renew" \
--scope "user:read user:write" \
--client-uri "https://portal.example.com" \
--logo-uri "https://portal.example.com/logo.png"
# 4. Verify the setup
uv run python -m authly admin client list
uv run python -m authly admin scope list# View client details (without secret)
uv run python -m authly admin client show <client-id>
# Regenerate a compromised secret
uv run python -m authly admin client regenerate-secret <client-id>
# Update client metadata
uv run python -m authly admin client update <client-id> \
--name "Updated Portal Name" \
--logo-uri "https://portal.example.com/new-logo.png"# Create hierarchical scopes
uv run python -m authly admin scope create \
--name "api:read" \
--description "Read API resources"
uv run python -m authly admin scope create \
--name "api:write" \
--description "Write API resources"
uv run python -m authly admin scope create \
--name "api:delete" \
--description "Delete API resources"
# Create default scopes (automatically granted)
uv run python -m authly admin scope create \
--name "openid" \
--description "OpenID Connect authentication" \
--default
uv run python -m authly admin scope create \
--name "profile" \
--description "User profile information" \
--default
# View default scopes
uv run python -m authly admin scope defaultsWhen having authentication issues, use these commands to diagnose:
# 1. Check configuration and paths
uv run python -m authly admin auth info
# 2. Verify authentication status
uv run python -m authly admin auth whoami --verbose
# 3. Check API connectivity
uv run python -m authly admin status
# 4. Re-authenticate if needed
uv run python -m authly admin auth login
# 5. For debugging, show tokens (careful in production!)
uv run python -m authly admin auth login --show-token# Get client list in JSON format
clients=$(python -m authly admin client list --output json)
echo "$clients" | jq '.clients[].client_id'
# Create client and extract client_id
client_info=$(python -m authly admin client create \
--name "Automated Client" \
--type confidential \
--redirect-uri "https://example.com/callback" \
--output json)
client_id=$(echo "$client_info" | jq -r '.client_id')
echo "Created client: $client_id"#!/bin/bash
# Create multiple scopes
scopes=("read" "write" "delete" "admin")
descriptions=("Read access" "Write access" "Delete access" "Admin access")
for i in "${!scopes[@]}"; do
python -m authly admin scope create \
--name "${scopes[$i]}" \
--description "${descriptions[$i]}"
done- name: Setup Authly Admin
run: |
# Non-interactive login for CI
python -m authly admin auth login \
--username "${{ secrets.AUTHLY_ADMIN_USER }}" \
--password "${{ secrets.AUTHLY_ADMIN_PASS }}"
# Create deployment client
python -m authly admin client create \
--name "Production Deploy" \
--type confidential \
--redirect-uri "${{ env.PRODUCTION_CALLBACK_URL }}" \
--output json > client.json0- Success1- General error2- Authentication error3- Permission denied4- Resource not found5- Validation error
$ python -m authly admin client show invalid-client
โ Error: Client not found
Client ID 'invalid-client' does not exist or has been deleted.
Exit code: 4# Enable verbose output with resource manager details
export AUTHLY_LOG_LEVEL=DEBUG
python -m authly admin status --verbose
# Show resource mode detection
python -c "
from authly.core.mode_factory import AuthlyModeFactory
print(f'Detected mode: {AuthlyModeFactory.detect_mode()}')
print(f'CLI mode check: {AuthlyModeFactory.is_cli_mode()}')
"
# Show HTTP requests
export AUTHLY_DEBUG_HTTP=true
python -m authly admin client list# Test CLI mode resource management
AUTHLY_MODE=cli python -m authly admin status
# Compare with other modes (requires running server)
AUTHLY_MODE=production python -m authly admin status
AUTHLY_MODE=embedded python -m authly admin status
# Force different pool settings for testing
AUTHLY_MODE=testing python -m authly admin status --verbose# Test API connectivity with CLI mode
python -m authly admin status
# Test authentication with resource manager info
python -m authly admin auth whoami
# Show detailed connection and resource info
python -m authly admin status --verbose- Never share admin tokens or include them in scripts
- Use environment variables for automation
- Tokens automatically expire and refresh
- Logout clears all stored credentials
- Use dedicated admin accounts, not your personal account
- Implement role-based access for admin operations
- Monitor admin API access through audit logs
- Restrict admin API to localhost or secure networks
- Use
--confirmflags in production scripts to avoid accidental changes - Always verify operations with
--dry-runwhen available - Keep CLI tools updated for security patches
- Use JSON output for parsing to avoid format changes
# Check CLI mode is using correct database
AUTHLY_LOG_LEVEL=DEBUG python -m authly admin status
# Test with different pool settings
AUTHLY_MODE=testing python -m authly admin status # Larger pool for testing# Verify mode detection
python -c "
from authly.core.mode_factory import AuthlyModeFactory
print(f'Current mode: {AuthlyModeFactory.detect_mode()}')
print(f'Pool settings: {AuthlyModeFactory.get_pool_settings(AuthlyModeFactory.detect_mode())}')
"
# Force CLI mode explicitly
AUTHLY_MODE=cli python -m authly admin client list# Check if admin API is enabled on the server
curl -s http://localhost:8000/admin/health | jq
# Test with verbose logging
AUTHLY_LOG_LEVEL=DEBUG python -m authly admin status --verboseFor frequent CLI operations, consider these optimizations:
# Use CLI mode for optimal performance
export AUTHLY_MODE=cli
# Batch operations in scripts
python -m authly admin client list --output json | jq '.clients[].client_id'
# Use connection pooling benefits
# CLI mode maintains connections for up to 1 minute for rapid successive commands| Scenario | Recommended Mode | Reason |
|---|---|---|
| Local Development | cli |
Optimized for quick admin tasks |
| Production Admin | production |
Uses same settings as server |
| CI/CD Scripts | cli or testing |
Fast, minimal resource usage |
| Debugging | testing |
Larger pool, detailed logging |
This CLI guide covers all administrative operations for the Authly OAuth 2.1 + OpenID Connect 1.0 authorization server, including the unified resource manager architecture and CLI mode optimizations. For API integration details, see the API Reference.