CLI Tools
Reference for all three Singularity CLI entry points -- services, tasks, and scripts -- with complete command listings, flags, and usage examples.
Singularity exposes three CLI tools, each registered as a console entry point in pyproject.toml. They are available after installation (uv sync) without needing to invoke Python directly.
# pyproject.toml
[project.scripts]
services = "cli.services:main"
tasks = "cli.tasks:main"
scripts = "cli.scripts:main"Every command is built with Click and follows a consistent pattern: <tool> <command> [arguments] [options]. Running any tool without a subcommand prints its help text.
All CLI errors are displayed as Rich-formatted panels with color-coded titles, contextual details, and actionable hints that explain what went wrong and how to fix it.
Services CLI
Manage the full lifecycle of Singularity services -- discover, create, inspect, disable, delete, validate, and visualize dependencies.
singularity services list
List all discovered services with their endpoints and RPC status.
# Default compact listing
services list
# Detailed table with path, endpoint, type, and RPC status
services list --detailed
# Include disabled and core services
services list --all
# JSON output for programmatic consumption
services list --json
# Combine flags
services list --detailed --allOptions:
| Flag | Short | Description |
|---|---|---|
--detailed | -d | Show path segments, endpoint, type (service/webhook), and RPC |
--all | -a | Include disabled and core (__base) services |
--json | -j | Output as JSON array |
Example output (compact):
Found 5 active service(s):
Name | Endpoint | RPC
--------------------------------------------------
users | /api/v1/users | Yes
payments | /api/v1/payments | Yes
stripe [wh] | /api/v1/stripe | No
notifications | /api/v1/notifications | No
analytics | /api/v1/analytics | Noservices info
Show detailed information about a specific service including methods, HTTP exposed routes, RPC settings, and webhook events.
services info paymentsExample output:
Service: payments
Path: services/v1/payments
Module: services.v1.payments.service
API Endpoint: /api/v1/payments
Class: PaymentsService
Status: Active
Methods:
- get /api/v1/payments
- post /api/v1/payments
HTTP Exposed:
- POST /api/v1/payments/refund (post_refund)
- GET /api/v1/payments/status (get_status)
Attributes:
rpc_exposed: True
blacklist: ['public']singularity generate service
Scaffold a new service with boilerplate code. Supports templates and mixins for common patterns.
# Basic CRUD service
singularity generate service users
# Nested path with description
singularity generate service v1/users -d "User management service"
# Minimal template with auth
singularity generate service v1/auth --template minimal --auth
# Webhook service with database access
singularity generate service v1/stripe --template webhook --db
# Service with RPC and custom methods
singularity generate service billing --rpc --methods get,post
# Service with WebSocket support
singularity generate service chat --websocket
# Overwrite existing service
singularity generate service users --overwriteArguments and Options:
| Parameter | Description |
|---|---|
SERVICE_NAME | Simple name (users) or nested path (v1/users) |
--description, -d | Service description |
--template, -t | Base template: crud (default), minimal, empty, webhook |
--methods, -m | Comma-separated HTTP methods (overrides template default) |
--rpc | Enable RPC exposure (rpc_exposed = True) |
--websocket, --ws | Add a WebSocket endpoint |
--auth | Add JWT authentication dependency |
--db | Add database session dependency |
--overwrite, -i | Overwrite existing service files |
Templates:
| Template | Methods | Acquire | Description |
|---|---|---|---|
crud | GET, POST, PUT, DELETE | Yes | Full CRUD operations with DB session |
minimal | GET, POST | Yes | Lightweight service with basic operations |
empty | (none) | No | Bare skeleton for fully custom services |
webhook | POST (via BaseWebhook) | Yes | Webhook receiver with signature verification |
services delete
Remove or disable a service. Requires either --soft or --hard.
# Soft delete -- disable without removing files
services delete old_service --soft
# Hard delete -- permanently remove files
services delete old_service --hard
# Skip confirmation prompt
services delete old_service --hard --force| Flag | Description |
|---|---|
--soft | Add to disabled list; manager skips it on startup. Files remain intact. |
--hard | Permanently delete the service directory from disk. |
--force, -f | Skip the confirmation prompt (hard delete only). |
Hard delete is irreversible. The CLI lists all files that will be removed and asks for confirmation unless --force is used.
services enable
Re-enable a previously soft-deleted (disabled) service.
services enable old_serviceAfter enabling, restart the server to load the service.
services validate
Validate a service name and preview what would be created, without writing any files.
services validate v1/analytics
# Preview with specific options
services validate v1/analytics --template crud --rpc --authExample output:
Name: v1/analytics
Class: AnalyticsService
Directory: services/v1/analytics
Service file: services/v1/analytics/service.py
API Endpoint: /api/v1/analytics
Configuration:
Template: crud
Methods: GET, POST, PUT, DELETE
RPC: Yes
Acquire: Yes
WebSocket: No
Auth: Yes
Ready to create. Run:
singularity generate service v1/analytics --template crud --rpc --authsingularity services graph
Visualize the service dependency graph. Detects RPC descriptors, remote Microservice descriptors, and blacklist declarations.
# ASCII output in the terminal
services graph
# Include disabled and core services
services graph --all
# JSON output
services graph --json
# DOT format for Graphviz
services graph --dot
# Pipe to Graphviz to render as PNG
services graph --dot | dot -Tpng -o deps.pngOptions:
| Flag | Short | Description |
|---|---|---|
--json | -j | Output as JSON with nodes, edges, remote_edges, and blocked arrays |
--dot | Output as DOT (Graphviz) format for visualization | |
--all | -a | Include disabled and core services |
Example output (ASCII):
Service Dependencies:
Local RPC:
orders ──> payments
orders ──> users
Remote (cross-deployment):
invoices ──> billing (https://billing.internal:8000)
Blacklisted:
payments x── public
Isolated (no dependencies, not depended on):
analytics
notificationsservices play
Interactive playground for testing a service with mocked dependencies. Instantiates the service using the testing harness (ServiceTestClient + TestAcquire) and drops into a REPL.
# Start a playground session
services play users
# Nested service path
services play v1/billingExample session:
Singularity Playground -- users (UsersService)
Available methods: get, post, put, delete
RPC dependencies: billing (auto-mocked)
Commands: .help .rpc .ms .calls .quit
> users> get()
{"status": "ok", "users": []}
> users> post(data={"name": "John"})
{"status": "created", "data": {"name": "John"}}
> users> .rpc billing get_balance {"balance": 100}
OK: billing.get_balance -> {"balance": 100}
> users> .calls
RPC billing.get_balance({})
> users> .quitDot commands:
| Command | Description |
|---|---|
.help | Show available methods with signatures |
.rpc <name> <method> <json> | Set a mock RPC response |
.ms <name> <method> <json> | Set a mock Microservice response |
.calls | Show all recorded RPC/MS calls |
.quit | Exit the playground |
The playground auto-detects RPC and Microservice descriptors on the service class and creates empty mocks for each. You can override responses at any time with .rpc and .ms commands.
services stubs
Generate typed Python stub classes from all RPC-exposed services. The stubs provide IDE autocomplete for inter-service RPC calls.
# Generate to the default path
services stubs
# Generate to a custom path
services stubs --output ./my_stubs.pyOptions:
| Flag | Short | Default | Description |
|---|---|---|---|
--output | -o | singularity/rpc/stubs.py | Output file path |
Example output:
"""
Auto-generated RPC stubs -- do not edit.
Run `services stubs` to regenerate.
"""
from typing import Any
class PaymentsRPC:
"""Stub for 'payments' service."""
async def get(self) -> Any: ...
async def post(self, data: dict) -> Any: ...
async def get_status(self, payment_id: str) -> Any: ...
class UsersRPC:
"""Stub for 'users' service."""
async def get(self) -> Any: ...
async def post(self, data: dict) -> Any: ...Stubs are generated via introspection -- they reflect the actual method signatures of your services. Regenerate after adding or modifying RPC-exposed service methods.
services dashboard
Open a live terminal dashboard (TUI) for browsing services, dependencies, hooks, and lifecycle info. Built with Textual and requires the optional dashboard extra.
# Install the dashboard extra
uv sync --extra dashboard
# Launch the dashboard
services dashboardLayout:
┌─────────────────────────────────────────────────────────┐
│ Singularity Dashboard [q] quit [?] help │
├────────────────────────┬────────────────────────────────┤
│ Services (5) │ Service Detail │
│ ───────────────── │ ───────────────────────── │
│ ● users [RPC] │ Name: users │
│ ● payments [RPC] │ Endpoint: /api/v1/users │
│ ● orders │ Methods: GET POST PUT DELETE │
│ ○ analytics [disabled]│ RPC: Yes │
│ ◆ stripe [webhook] │ Hooks: before(all), after(all)│
├────────────────────────┴────────────────────────────────┤
│ Dependency Graph │
│ users ──▸ payments orders ──▸ payments │
├─────────────────────────────────────────────────────────┤
│ Logs │
│ 12:03:01 INFO Discovered 5 service(s) │
│ 12:03:01 INFO Dependency graph rendered │
└─────────────────────────────────────────────────────────┘Keybindings:
| Key | Action |
|---|---|
↑ / ↓ | Navigate service list |
Enter | Select service (updates detail panel) |
r | Refresh service discovery |
g | Toggle dependency graph panel |
l | Toggle log panel |
? | Show keyboard shortcuts |
q | Quit |
The dashboard is read-only -- it uses ServiceDiscovery introspection and does not require a running server. Service status indicators: ● active, ○ disabled, ◆ webhook.
Tasks CLI
Manage, inspect, run, and serve background tasks powered by Celery and Redis.
singularity tasks list
List all discovered background tasks with their descriptions and parameter counts.
tasks listExample output:
Found 3 tasks:
----------------------------------------------------------------------
Name | Description | Params
----------------------------------------------------------------------
send_email | Send a transactional email | 3
process_order | Process an e-commerce order | 3
generate_report | Generate a PDF report | 2
Use 'tasks info <task_name>' for parameter details.tasks info
Show detailed information about a specific task, including its full parameter signature, types, defaults, and configuration.
tasks info send_emailExample output:
Task: send_email
Send a transactional email
Parameters:
--------------------------------------------------
Name Type Required Default
--------------------------------------------------
to str Y -
subject str Y -
body str Y -
Config:
Notifications: log, callback
Max Retries: 3 | Retry Delay: 60s | Time Limit: 3600ssingularity generate task
Generate a new task file with boilerplate in tasks/executable/.
# Create a task with a description
singularity generate task send_notification -d "Send push notifications to users"
# Overwrite an existing task
singularity generate task send_notification -d "Updated notification logic" --overwrite| Option | Short | Description |
|---|---|---|
--description | -d | Task description |
--overwrite | -i | Overwrite existing task file |
The generated file includes the @task decorator, a stub function with a placeholder parameter, and an @on_complete callback.
tasks run
Trigger a task manually from the command line.
# Run with keyword arguments (JSON)
tasks run send_email -k '{"to": "test@example.com", "subject": "Hello", "body": "World"}'
# Run with a countdown delay (task starts in 60 seconds)
tasks run process_order -k '{"order_id": "ord_123", "items": []}' -c 60
# Positional arguments
tasks run send_email test@example.com "Hello" "World"| Option | Short | Description |
|---|---|---|
--kwargs | -k | JSON dictionary of keyword arguments |
--countdown | -c | Delay in seconds before the task starts |
The --kwargs flag accepts both JSON strings and Python dict literals (parsed via ast.literal_eval as a fallback).
tasks result
Check the status and result of a previously submitted task.
tasks result abc12345-task-idExample output:
Task ID: abc12345-task-id
State: SUCCESS
Result: {'status': 'sent', 'to': 'test@example.com'}States: PENDING, STARTED, SUCCESS, FAILURE, REVOKED.
singularity tasks worker
Start a Celery worker instance to consume and execute tasks.
# Default worker (2 threads)
tasks worker
# High-concurrency worker with gevent pool
tasks worker --concurrency 8 --pool gevent
# Worker with Beat scheduler for periodic tasks
tasks worker --beat
# Debug-level logging
tasks worker --loglevel debug
# Autoscaling between 2 and 10 workers
tasks worker --autoscale 10,2
# Consume from specific queues
tasks worker --queues celery,priority| Option | Type | Default | Description |
|---|---|---|---|
--concurrency | int | 2 | Number of concurrent workers |
--loglevel | choice | info | debug, info, warning, error, critical |
--queues | str | celery | Comma-separated queue names |
--hostname | str | auto | Custom worker hostname |
--max-tasks-per-child | int | 1000 | Replace child after N tasks |
--prefetch-multiplier | int | 1 | Messages to prefetch per worker |
--pool | choice | threads | prefork, eventlet, gevent, threads, solo |
--autoscale | str | -- | Autoscale range as max,min |
--beat | flag | -- | Enable Celery Beat scheduler |
When using --pool gevent, the CLI automatically applies gevent monkey patching before any other imports. This is handled transparently -- you do not need to patch manually.
Scripts CLI
Manage database migration scripts, data patches, and maintenance operations.
scripts list
List all discovered executable scripts with their auto-run status, rerun flag, deprecation state, affected tables, and descriptions.
# Detailed listing (default)
scripts list
# Simplified listing
scripts list --simpleExample output (detailed):
Available Scripts (4 found)
=================================================================================
ID Script Name Auto-run Rerun Deprecated Affected Tables
----------------------------------------------------------------------------------
1 cleanup_orphaned_records ON OFF No temp_uploads
2 create_stripe_products ON OFF No products, prices
3 old_migration_v1 OFF OFF Yes (none)
4 seed_initial_data ON ON No users, rolessingularity generate script
Generate a new script file with proper BaseScript boilerplate.
# Create with a description
singularity generate script add_user_roles -d "Add default user roles to the database"
# Overwrite an existing script
singularity generate script add_user_roles -d "Updated roles" --overwrite| Option | Short | Description |
|---|---|---|
--description | -d | Script description |
--overwrite | -i | Overwrite existing script file |
The generated file includes:
BaseScriptinheritance with constructorexecute(),rollback(), andverify()method stubs- Path setup for imports
- CLI entry point (
run_cli())
scripts run
Execute a script by name or numeric ID. Supports run (default), rollback, and status subcommands.
# Run a script (default action)
scripts run add_user_roles
# Force rerun even if already succeeded
scripts run add_user_roles run --force
# Check execution status
scripts run add_user_roles status
# Roll back a previously executed script
scripts run add_user_roles rollback
# Run by numeric ID
scripts run 2
# Check status by ID
scripts run 2 status| Argument | Description |
|---|---|
IDENTIFIER | Script name or numeric ID from the list |
COMMAND | run (default), rollback, or status |
scripts history
Display the full execution history from the script_run_tracker database table. Shows status, timestamps, hash changes, and error messages.
scripts historyExample output:
Executed Scripts History (3 total)
============================================================
Script Name Status Executed At Modified Hash
------------------------------------------------------------
create_stripe_products SUCCESS 2024-06-15 10:23:01 Current a1b2c3d4e5f6...
cleanup_orphaned_records SUCCESS 2024-06-15 10:23:02 CHANGED f6e5d4c3b2a1...
old_migration_v1 ROLLED_BACK 2024-06-14 08:15:30 Missing (none)Status indicators:
- Success -- Script completed and verified
- Failed -- Script threw an exception (error message shown below)
- Pending -- Script started but has not finished
- Rolled back -- Script was rolled back via CLI
scripts sync-hashes
Populate missing content_hash values for scripts that were executed before hash tracking was introduced. This updates the database with current file hashes so that future change detection works correctly.
scripts sync-hashesscripts startup
Run all auto-run scripts, simulating the application startup behavior. Uses PostgreSQL advisory locks for multi-worker coordination.
scripts startupCommand Summary
| Command | Description |
|---|---|
scripts list | List all discovered scripts with metadata |
scripts list --simple | Compact listing without details |
singularity generate script <name> -d "desc" | Generate a new script with boilerplate |
scripts run <name|id> | Execute a script |
scripts run <name|id> rollback | Roll back a script |
scripts run <name|id> status | Check script execution status |
scripts history | Show full execution history from the database |
scripts sync-hashes | Backfill missing content hashes |
scripts startup | Run all auto-run scripts |
Entry Points
All three CLIs are registered as console scripts in pyproject.toml:
[project.scripts]
scripts = "cli.scripts:main"
tasks = "cli.tasks:main"
services = "cli.services:main"After running uv sync, these commands are available directly in your shell without a python -m prefix. The src directory is included in pythonpath via the hatch build configuration, so all internal imports (e.g., services.__base.discovery, tasks.core.runner) resolve correctly.
If you are running commands outside of the installed package (e.g., during development), use singularity services list to ensure the correct Python path and virtual environment are used.
Database Scripts
Write, track, and manage database migration scripts with rollback support, hash-based change detection, parallel execution with table locking, and full execution history.
Testing
Unit test services, mock RPC calls and microservices, verify webhooks, and run integration tests using Singularity's built-in testing harness.