# CLI Reference

Source: https://wiki.faucetdb.ai/cli-reference

Faucet is a single binary with subcommands for managing the server, databases, API keys, roles, and more.

```
faucet <command> [subcommand] [flags]
```

## Global Flags

| Flag | Default | Description |
|------|---------|-------------|
| `--config` | `./faucet.yaml` | Path to config file |
| `--data-dir` | `~/.faucet` | Data directory for SQLite config database |

## faucet serve

Start the Faucet API server.

```bash
faucet serve [flags]
```

By default, `faucet serve` starts the server **in the background** and returns control to your terminal. This means you can immediately run other faucet commands (`faucet db add`, `faucet admin create`, etc.) without opening a new terminal session.

**Flags:**

| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--port` | `-p` | `8080` | HTTP listen port |
| `--host` | | `0.0.0.0` | HTTP listen host |
| `--no-ui` | | `false` | Disable the embedded admin UI |
| `--dev` | | `false` | Enable development mode (verbose logging, CORS *, foreground) |
| `--foreground` | | `false` | Run in foreground / blocking mode (for Docker, systemd, etc.) |

**Examples:**

```bash
# Start server in background (default)
faucet serve

# Custom port
faucet serve --port 9090

# Development mode (runs in foreground with verbose logging)
faucet serve --dev

# Run in foreground (for Docker, systemd, Kubernetes)
faucet serve --foreground

# Without admin UI
faucet serve --no-ui

# Custom data directory
faucet serve --data-dir /var/lib/faucet

# Bind to localhost only
faucet serve --host 127.0.0.1 --port 8080
```

**Background mode output:**

```
 _____ _   _   _  ___ ___ _____
|  ___/ \ | | | |/ __| __|_   _|
| |_ / _ \| |_| | (__|  _| | |
|_| /_/ \_\___,_|\___|___| |_|

  Faucet v0.1.14 | Database → API in seconds
  Listening on http://0.0.0.0:8080
  Admin UI:   http://localhost:8080/
  OpenAPI:    http://localhost:8080/openapi.json
  MCP:        http://localhost:8080/mcp

  First run detected! Set up your admin account:
    Web UI:  http://localhost:8080/setup
    CLI:     faucet admin create --email admin@example.com --password changeme123

  Server running in background (PID 12345)
  Logs: /home/user/.faucet/faucet.log

Use 'faucet stop' to stop the server.
Use 'faucet status' to check server health.
```

After the server starts, you can keep using the same terminal. Open the admin UI to finish setup in the browser, or use the CLI:

```bash
faucet serve
faucet admin create --email admin@example.com --password changeme123
```

**On startup, the server:**
1. Initializes the SQLite config store at the data directory
2. Registers database drivers (postgres, mysql, mssql, oracle, snowflake, sqlite)
3. Connects all active database services from the config
4. Initializes the authentication service
5. Starts the HTTP server with all routes and middleware
6. Writes a PID file to `~/.faucet/faucet.pid`

**Endpoints served:**

| URL | Description |
|-----|-------------|
| `http://host:port/` | Admin UI |
| `http://host:port/admin` | Redirects to the admin UI (older links) |
| `http://host:port/setup` | First-run setup wizard |
| `http://host:port/healthz` | Liveness probe |
| `http://host:port/readyz` | Readiness probe |
| `http://host:port/openapi.json` | Combined OpenAPI spec |
| `http://host:port/api/v1/...` | REST API |

**Server logs:** When running in background mode, logs are written to `~/.faucet/faucet.log`. Use `--dev` for foreground mode with live log output to stderr.

---

## faucet stop

Stop a background Faucet server.

```bash
faucet stop
```

Sends a graceful shutdown signal to the running server. The server drains in-flight requests (up to 30 seconds), closes all database connections, and exits cleanly.

**Example:**

```bash
faucet stop
# Stopping Faucet server (PID 12345)...
# Server stopped.
```

---

## faucet status

Check if the Faucet server is running.

```bash
faucet status
```

Reports the server's process state and HTTP health.

**Example output (running):**

```
Server is running (PID 12345)
  Health:  http://127.0.0.1:8080/healthz (200)
  Logs:    /home/user/.faucet/faucet.log
```

**Example output (not running):**

```
Server is not running (no PID file found).
```

---

## faucet config

Manage the Faucet configuration file.

### faucet config init

Create a default `faucet.yaml` configuration file in the current directory.

```bash
faucet config init [flags]
```

**Flags:**

| Flag | Description |
|------|-------------|
| `--force` | Overwrite existing config file |

**Example:**

```bash
faucet config init
faucet config init --force
```

### faucet config show

Display the current effective configuration.

```bash
faucet config show
```

---

## faucet db

Manage database connections. Aliases: `service`, `database`.

### faucet db add

Add a new database connection. Describe the connection either with separate flags (`--host`, `--user`, `--password`, ...) or with one `--dsn` connection string. With separate flags, Faucet builds a correctly escaped connection string for the driver, so passwords with special characters need no URL-encoding. If you leave out the name, the driver or the connection details, you are prompted for them (the connection as a DSN).

```bash
faucet db add [flags]
```

**Flags:**

| Flag | Description |
|------|-------------|
| `--name` | Service name; becomes the API path `/api/v1/<name>` |
| `--driver` | Database driver: `postgres`, `mysql` (also for MariaDB), `mssql`, `oracle`, `snowflake`, `sqlite` |
| `--host` | Database host |
| `--port` | Database port (defaults to 5432, 3306, 1433 or 1521 for the driver) |
| `--user` | Database user |
| `--password` | Database password |
| `--password-prompt` | Prompt for the password without echoing it, so it stays out of shell history |
| `--param` | Extra driver option as `key=value`, repeatable (for example `--param sslrootcert=/ca.pem`) |
| `--database` | Database name (Oracle: the service name; Snowflake: the database) |
| `--ssl-mode` | TLS setting: Postgres `sslmode`, MySQL `tls`, SQL Server `encrypt`, Oracle `true` |
| `--path` | SQLite database file path |
| `--account` | Snowflake account identifier (`orgname-accountname`) |
| `--warehouse` | Snowflake warehouse |
| `--role` | Snowflake role |
| `--dsn` | Complete connection string, instead of the separate flags above |
| `--label` | Human-readable label (defaults to name) |
| `--schema` | Database schema to expose (default depends on driver; for Snowflake it is also used in the connection) |
| `--private-key-path` | Path to private key file (for Snowflake key-pair auth) |

**Examples:**

```bash
# PostgreSQL with separate fields (prompts for the password)
faucet db add --name mydb --driver postgres \
  --host db.example.com --user api --password-prompt --database mydb --ssl-mode require

# MySQL or MariaDB
faucet db add --name shop --driver mysql --host localhost --user root --password secret --database shop

# SQLite file
faucet db add --name local --driver sqlite --path ./data/app.db

# Snowflake with key-pair authentication
faucet db add --name analytics --driver snowflake \
  --account myorg-myaccount --user FAUCET_SVC --database ANALYTICS --schema PUBLIC \
  --warehouse COMPUTE_WH --private-key-path ~/.ssh/snowflake_key.p8

# Existing connection string
faucet db add --name mydb --driver postgres --dsn "postgres://user:pass@localhost/mydb"

# Interactive mode (prompts for each field)
faucet db add
```

::: tip Running server
`faucet db add` writes to the config store. A server that is already running loads it on its next start (`faucet stop && faucet serve`). Databases added in the admin UI or through `POST /api/v1/system/service` are live immediately.
:::

### faucet db list

List all registered database services. Alias: `ls`.

```bash
faucet db list [flags]
```

**Flags:**

| Flag | Default | Description |
|------|---------|-------------|
| `--json` | `false` | Output as JSON |

**Example output:**

```
NAME                 DRIVER       ACTIVE
----                 ------       ------
mydb                 postgres     yes
analytics            snowflake    yes
legacy               mysql        no
```

### faucet db remove

Remove a database service. Aliases: `rm`, `delete`.

```bash
faucet db remove <name>
```

**Example:**

```bash
faucet db remove legacy
```

### faucet db test

Test a database connection by attempting to connect and ping.

```bash
faucet db test <name>
```

**Example:**

```bash
faucet db test mydb
# Testing connection "mydb"... ok
```

### faucet db schema

Print the database schema as JSON. Optionally filter to a single table.

```bash
faucet db schema <name> [flags]
```

**Flags:**

| Flag | Description |
|------|-------------|
| `--table` | Show schema for a single table only |

**Examples:**

```bash
# Full schema
faucet db schema mydb

# Single table
faucet db schema mydb --table users
```

### faucet db lock

Lock the schema for a service, creating contracts for all tables. See [Schema Locking](https://wiki.faucetdb.ai/schema-locking) for details.

```bash
faucet db lock <service> [flags]
```

**Flags:**

| Flag | Description |
|------|-------------|
| `--table` | Lock a single table instead of all tables |
| `--mode` | Set lock mode: `auto` (default) or `strict` |

**Examples:**

```bash
# Lock all tables in auto mode
faucet db lock mydb

# Lock a specific table
faucet db lock mydb --table users

# Lock in strict mode
faucet db lock mydb --mode strict
```

### faucet db unlock

Remove schema contracts (unlock) for a service or table.

```bash
faucet db unlock <service> [flags]
```

**Flags:**

| Flag | Description |
|------|-------------|
| `--table` | Unlock a single table instead of all tables |

**Examples:**

```bash
# Unlock all tables
faucet db unlock mydb

# Unlock a specific table
faucet db unlock mydb --table users
```

### faucet db diff

Compare locked contracts against the live database schema. Shows additive and breaking changes.

```bash
faucet db diff <service> [flags]
```

**Flags:**

| Flag | Description |
|------|-------------|
| `--table` | Check a specific table only |
| `--json` | Output as JSON (useful for CI) |

**Examples:**

```bash
# Check all locked tables
faucet db diff mydb

# Check a specific table
faucet db diff mydb --table users

# JSON output for CI pipelines
faucet db diff mydb --json
```

### faucet db promote

Update a contract to match the current live schema. This accepts the current database state as the new API contract.

```bash
faucet db promote <service> [flags]
```

**Flags:**

| Flag | Description |
|------|-------------|
| `--table` | Promote a specific table |
| `--all` | Promote all locked tables |

**Examples:**

```bash
# Promote a specific table
faucet db promote mydb --table users

# Promote all tables
faucet db promote mydb --all
```

---

## faucet key

Manage API keys. Alias: `apikey`.

### faucet key create

Create a new API key. The raw key is shown once and cannot be retrieved again.

```bash
faucet key create [flags]
```

**Flags:**

| Flag | Required | Description |
|------|----------|-------------|
| `--role` | Yes | Role name to bind the key to |
| `--label` | No | Human-readable label for the key |

**Examples:**

```bash
faucet key create --role readonly --label "CI pipeline"
faucet key create --role admin
```

**Output:**

```
API Key created:

  Key:   faucet_a1b2c3d4e5f6...
  Role:  readonly
  Label: CI pipeline

  Save this key now - it cannot be retrieved again.
```

### faucet key list

List all API keys (without exposing the actual key values). Alias: `ls`.

```bash
faucet key list [flags]
```

**Flags:**

| Flag | Default | Description |
|------|---------|-------------|
| `--json` | `false` | Output as JSON |

**Example output:**

```
PREFIX       ROLE             LABEL                    ACTIVE
------       ----             -----                    ------
faucet_a1   readonly         CI pipeline              yes
faucet_b2   admin            Admin UI                 yes
```

### faucet key revoke

Revoke an API key by its prefix, preventing further authenticated requests.

```bash
faucet key revoke <prefix>
```

**Example:**

```bash
faucet key revoke faucet_a1
```

---

## faucet role

Manage RBAC roles.

### faucet role create

Create a new role. Use `--verbs` to grant an initial access rule. Without it, the role has no rules, and API keys bound to it are denied (`403`) until you run [`faucet role grant`](https://wiki.faucetdb.ai/cli-reference#faucet-role-grant).

```bash
faucet role create [flags]
```

**Flags:**

| Flag | Required | Default | Description |
|------|----------|---------|-------------|
| `--name` | Yes | | Role name |
| `--description` | No | | Role description |
| `--verbs` | No | | Verbs for the initial rule: comma-separated `GET,POST,PUT,PATCH,DELETE`, or `*` for all |
| `--service` | No | `*` | Service the initial rule applies to (`*`, an exact name, or a `prefix*` pattern) |
| `--component` | No | `*` | Component the initial rule applies to (`*`, `_table/*`, `_table/customers`, ...) |

**Examples:**

```bash
faucet role create --name readonly --verbs GET --description "Read-only access to all services"
faucet role create --name admin --verbs '*' --description "Full access"
faucet role create --name orders-writer --service mydb --component "_table/orders" --verbs GET,POST,PATCH
```

### faucet role grant

Add an access rule to an existing role. Existing rules are kept.

```bash
faucet role grant [flags]
```

**Flags:**

| Flag | Required | Default | Description |
|------|----------|---------|-------------|
| `--role` | Yes | | Role name |
| `--verbs` | Yes | | Comma-separated `GET,POST,PUT,PATCH,DELETE`, or `*` for all |
| `--service` | No | `*` | Service the rule applies to (`*`, an exact name, or a `prefix*` pattern) |
| `--component` | No | `*` | Component the rule applies to (`*`, `_table/*`, `_table/customers`, ...) |

**Examples:**

```bash
faucet role grant --role readonly --verbs GET
faucet role grant --role readonly --service mydb --component "_table/orders" --verbs GET,POST
faucet role grant --role admin --verbs '*'
```

### faucet role list

List all roles. Alias: `ls`.

```bash
faucet role list [flags]
```

**Flags:**

| Flag | Default | Description |
|------|---------|-------------|
| `--json` | `false` | Output as JSON |

**Example output:**

```
NAME                 DESCRIPTION                              ACTIVE   RULES
----                 -----------                              ------   -----
readonly             Read-only access to all services         yes      2 rule(s): mydb
admin                Full access                              yes      0 rule(s)
```

---

## faucet admin

Manage admin users.

### faucet admin create

Create a new admin user. If `--password` is omitted, you will be prompted interactively (with confirmation).

```bash
faucet admin create [flags]
```

**Flags:**

| Flag | Required | Description |
|------|----------|-------------|
| `--email` | Yes | Admin email address |
| `--password` | No | Admin password (prompted if omitted) |
| `--name` | No | Admin display name |

**Examples:**

```bash
# With password flag
faucet admin create --email admin@example.com --password changeme123

# Interactive password prompt
faucet admin create --email admin@example.com

# With display name
faucet admin create --email admin@example.com --name "Admin User"
```

Password must be at least 8 characters.

### faucet admin list

List all admin accounts. Alias: `ls`.

```bash
faucet admin list [flags]
```

**Flags:**

| Flag | Default | Description |
|------|---------|-------------|
| `--json` | `false` | Output as JSON |

---

## faucet mcp

Start the MCP (Model Context Protocol) server for AI agent integration.

```bash
faucet mcp [flags]
```

**Flags:**

| Flag | Default | Description |
|------|---------|-------------|
| `--transport` | `stdio` | Transport mode: `stdio` or `http` |
| `--port` | `3001` | HTTP port (only used with `--transport http`) |

**Examples:**

```bash
# stdio mode for Claude Desktop
faucet mcp

# HTTP mode for remote access
faucet mcp --transport http --port 3001

# Custom data directory
faucet mcp --data-dir /var/lib/faucet
```

See [MCP Server](https://wiki.faucetdb.ai/mcp-server) for complete documentation.

---

## faucet openapi

Generate an OpenAPI 3.1 specification for one or all database services.

```bash
faucet openapi [service] [flags]
```

**Flags:**

| Flag | Short | Description |
|------|-------|-------------|
| `--all` | | Generate combined spec for all services |
| `--output` | `-o` | Write spec to file instead of stdout |
| `--base-url` | | Base URL for the API server (default `http://localhost:8080`) |

**Examples:**

```bash
# Single service
faucet openapi mydb

# All services
faucet openapi --all

# Write to file
faucet openapi mydb -o spec.json

# Pipe to other tools
faucet openapi --all | jq '.paths | keys'
```

---

## faucet benchmark

Run a load test against a database to measure query throughput and latency.

```bash
faucet benchmark [flags]
```

**Flags:**

| Flag | Default | Description |
|------|---------|-------------|
| `--driver` | `postgres` | Database driver |
| `--dsn` | (required) | Connection string |
| `--duration` | `30s` | Test duration |
| `--concurrency` | `10` | Number of concurrent workers |
| `--table` | (auto) | Table to query (auto-detected if omitted) |

**Examples:**

```bash
# Basic benchmark
faucet benchmark --dsn "postgres://localhost/mydb"

# With custom settings
faucet benchmark \
  --driver postgres \
  --dsn "postgres://localhost/mydb" \
  --duration 60s \
  --concurrency 50 \
  --table users
```

**Output:**

```
Faucet Benchmark
================
  driver:      postgres
  duration:    30s
  concurrency: 10

Connecting... ok
Detecting tables... using "users"
  query: SELECT * FROM "users" LIMIT 10

Running benchmark...

Results
-------
  Total queries:  45230
  Errors:         0
  QPS:            1507.7
  Latency p50:    0.65ms
  Latency p95:    1.2ms
  Latency p99:    3.1ms
  Latency max:    15.4ms
```

---

## faucet version

Print version, build, and runtime information.

```bash
faucet version [flags]
```

**Flags:**

| Flag | Default | Description |
|------|---------|-------------|
| `--json` | `false` | Output as JSON |

**Example output:**

```
faucet 0.1.14
  commit:  abc1234
  built:   2026-10-09T10:30:00Z
  go:      go1.25.6
  os/arch: darwin/arm64
```

**JSON output:**

```json
{
  "version": "0.1.14",
  "commit": "abc1234",
  "built": "2026-10-09T10:30:00Z",
  "go_version": "go1.25.6",
  "os": "darwin",
  "arch": "arm64"
}
```

## Related

- [Getting Started](https://wiki.faucetdb.ai/getting-started): the CLI quickstart
- [RBAC](https://wiki.faucetdb.ai/rbac): roles, verbs and API keys in depth
- [Schema Locking](https://wiki.faucetdb.ai/schema-locking): the `faucet db lock` workflow
- [MCP Server](https://wiki.faucetdb.ai/mcp-server): `faucet mcp` transports and client configs
- [Deployment](https://wiki.faucetdb.ai/deployment): running `faucet serve` in production
