CLI Reference
Horsies provides a clap-based CLI (horsies) for running workers, the scheduler, and validation checks. In Rust, tasks are registered at compile time, so the CLI takes a configuration source (config file path or database URL) instead of a Python module path.
Commands
Section titled “Commands”horsies worker
Section titled “horsies worker”Start a task worker.
horsies worker [CONFIG] [OPTIONS]Arguments:
| Argument | Description |
|---|---|
CONFIG | Path to a config file (TOML/JSON) or database URL (positional, optional) |
Options:
| Option | Default | Description |
|---|---|---|
-m, --module CONFIG | — | Config source (alternative to positional argument; takes precedence) |
-q, --queues QUEUES | default | Comma-separated queue names |
-c, --concurrency N | CPU count | Maximum concurrent tasks |
--max-claim-batch N | 2 | Max claims per queue per pass |
--max-claim-per-worker N | 0 | Max total claimed tasks (0=auto) |
--coalesce-notifies N | 100 | NOTIFY messages to drain per wake |
--loglevel LEVEL | info | debug, info, warning, error |
Examples:
# Start worker with a config filehorsies worker ./config/horsies.toml
# Start worker with a database URLhorsies worker -m "postgresql://user:pass@localhost/mydb"
# Custom concurrency and queueshorsies worker ./config/horsies.toml -q high,low --concurrency 8
# Debug logginghorsies worker ./config/horsies.toml --loglevel debug
# Production settingshorsies worker ./config/horsies.toml --concurrency 8 --max-claim-batch 4 --loglevel warningProgrammatic Alternative
Section titled “Programmatic Alternative”In most Rust projects, you start the worker directly in your binary:
use horsies::{Horsies, AppConfig, WorkerConfig};
#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { let mut app = Horsies::new(AppConfig::for_database_url("postgresql://..."))?;
// Register tasks my_task::register(&mut app)?;
// Start worker with defaults app.run_worker().await?;
// Or with custom config let worker_config = WorkerConfig { concurrency: 8, queues: vec!["high".into(), "low".into()], ..Default::default() }; app.run_worker_with(worker_config).await?;
Ok(())}horsies scheduler
Section titled “horsies scheduler”Start the scheduler service.
horsies scheduler [CONFIG] [OPTIONS]Arguments:
| Argument | Description |
|---|---|
CONFIG | Path to a config file or database URL |
Options:
| Option | Default | Description |
|---|---|---|
-m, --module CONFIG | — | Config source (alternative to positional argument) |
--loglevel LEVEL | info | debug, info, warning, error |
--check-interval N | from config | Override check interval in seconds (1-60) |
--dry-run | false | Validate schedules without starting the loop |
Examples:
# Start schedulerhorsies scheduler ./config/horsies.toml
# Debug logginghorsies scheduler ./config/horsies.toml --loglevel debug
# Validate schedules without runninghorsies scheduler ./config/horsies.toml --dry-runProgrammatic alternative:
app.run_scheduler().await?;horsies check
Section titled “horsies check”Validate configuration, task registration, and optionally broker connectivity without starting services.
For details on validation phases, see Startup Validation.
horsies check [CONFIG] [OPTIONS]Arguments:
| Argument | Description |
|---|---|
CONFIG | Path to a config file or database URL |
Options:
| Option | Default | Description |
|---|---|---|
-m, --module CONFIG | — | Config source (alternative to positional argument) |
--loglevel LEVEL | warning | debug, info, warning, error |
--live | false | Also connect to PostgreSQL, ensure the Horsies schema, and run SELECT 1 |
Examples:
# Validate config and task registrationhorsies check ./config/horsies.toml
# Include broker connectivity checkhorsies check ./config/horsies.toml --liveProgrammatic alternative:
app.check()?;// or with live DB check:app.check_live().await?;horsies web
Section titled “horsies web”Start the optional monitoring dashboard. Build the binary with the web Cargo
feature first.
horsies web CONFIG [OPTIONS]horsies web --database-url URL [OPTIONS]CONFIG is a TOML application configuration. --database-url selects the
standalone database-URL form. The two forms are mutually exclusive.
The server is observe-only. It does not run migrations or the task-history fleet gate.
Options:
| Option | Default | Description |
|---|---|---|
--database-url URL | — | Runtime query URL instead of CONFIG |
--session-database-url URL | — | Direct or session URL for LISTEN/NOTIFY |
--pgbouncer-transaction-mode | false | Treat the runtime URL as a PgBouncer transaction pool |
--host HOST | 127.0.0.1 | Bind interface or host |
--port PORT | 8600 | Bind port; zero requests an assigned port |
--auth MODE | none | none or trusted-header |
--trusted-header NAME | X-Forwarded-User | Trusted proxy identity header |
--enable-actions | false | Enable task and workflow actions |
--custom-css-url URL | — | Load a stylesheet after the bundled styles |
--loglevel LEVEL | info | debug, info, warning, error |
--auth none requires a loopback host. Trusted-header mode requires a reverse
proxy that strips or overwrites the identity header on every request.
# Local view-only dashboardhorsies web ./config/horsies.toml
# Trusted proxy with actionshorsies web ./config/horsies.toml \ --host 127.0.0.1 \ --auth trusted-header \ --trusted-header X-Forwarded-User \ --enable-actions
# PgBouncer transaction-pool deploymenthorsies web \ --database-url postgresql://app:secret@pool.example.com/horsies \ --session-database-url postgresql://app:secret@db.example.com/horsies \ --pgbouncer-transaction-modeSee Deployment and Authentication for the router factory, auth policies, custom CSS, and schema states.
horsies get-docs
Section titled “horsies get-docs”Fetch the full documentation locally as markdown files. Useful for AI agents (Claude Code, Cursor, Copilot, etc.) that need to read docs without web requests.
horsies get-docs [OPTIONS]Options:
| Option | Default | Description |
|---|---|---|
--output DIR | .horsies-docs | Output directory |
Examples:
# Fetch docs to default locationhorsies get-docs
# Custom output directoryhorsies get-docs --output my-docs/
# Update existing docs (idempotent -- overwrites cleanly)horsies get-docsUses git sparse checkout when git is available, falls back to tarball download otherwise. No app instance or database connection required.
Agent Skills (Repository)
Section titled “Agent Skills (Repository)”If you are using an AI coding agent from a source checkout, Horsies also ships guidance-oriented skill files in:
horsies/.agents/skills/
Available files:
SKILL.md— quick orientation and routingtasks.md— task authoring, send/retry, serialization, error handlingworkflows.md— DAG construction, handles, failure semantics, validationconfigs.md— configuration, scheduling, CLI checks, environment variables
These files are documentation-focused (no bundled scripts) and are intended for on-demand loading by agents that support markdown skill files.
Process Signals
Section titled “Process Signals”Both commands handle graceful shutdown:
| Signal | Behavior |
|---|---|
SIGTERM | Graceful shutdown |
SIGINT (Ctrl+C) | Graceful shutdown |
Workers wait for running tasks to complete before exiting.
Exit Codes
Section titled “Exit Codes”| Code | Meaning |
|---|---|
| 0 | Clean shutdown |
| 1 | Error (check logs) |
| 2 | Unsafe or invalid horsies web security arguments |
Environment Variables
Section titled “Environment Variables”export DATABASE_URL=postgresql://...horsies worker "$DATABASE_URL"The CLI does not inject DATABASE_URL into config files or load .env automatically. Use a config file path as the positional argument, or pass the database URL directly as the config source.
Logging can be controlled with RUST_LOG:
# Fine-grained log controlRUST_LOG=horsies=debug,sqlx=warn horsies worker ./config/horsies.tomlWhen RUST_LOG is set, it takes precedence over the --loglevel flag.
Deployment
Section titled “Deployment”Systemd
Section titled “Systemd”[Unit]Description=Horsies WorkerAfter=postgresql.service
[Service]Type=simpleUser=appWorkingDirectory=/appExecStart=/usr/local/bin/myapp-workerRestart=alwaysEnvironment=DATABASE_URL=postgresql://user:pass@localhost/db
[Install]WantedBy=multi-user.targetDocker
Section titled “Docker”FROM rust:1.75 AS builderWORKDIR /appCOPY . .RUN cargo build --release
FROM debian:bookworm-slimRUN apt-get update && apt-get install -y libssl3 ca-certificates && rm -rf /var/lib/apt/lists/*COPY --from=builder /app/target/release/myapp-worker /usr/local/bin/CMD ["myapp-worker"]Procfile
Section titled “Procfile”worker: ./target/release/myapp-workerscheduler: ./target/release/myapp-scheduler