> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pullbase.io/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI Reference

> Command reference for the pullbasectl utility.

<Tip>
  New to the CLI? Check out the [CLI Guide](/guides/pullbasectl) for workflows and examples.
</Tip>

`pullbasectl` ships with the Pullbase Docker image and is available inside the container at `/pullbasectl`. You can run it from the host by invoking the container or by copying the binary out of the image.

```bash theme={null}
# Run pullbasectl from the official image
alias pullbasectl='docker run --rm pullbaseio/pullbase:latest pullbasectl'
```

## Global options

These options are available on most commands:

| Flag                     | Description                                              |
| ------------------------ | -------------------------------------------------------- |
| `--server-url`           | Pullbase server base URL (e.g., `http://localhost:8080`) |
| `--admin-token`          | Admin JWT token for authentication                       |
| `--username`             | Admin username (alternative to `--admin-token`)          |
| `--password`             | Admin password (use with `--username`)                   |
| `--password-file`        | Path to file containing admin password                   |
| `--ca-cert`              | Path to CA certificate bundle for TLS verification       |
| `--insecure-skip-verify` | Skip TLS certificate verification (not recommended)      |

<Tip>
  Set the environment variable `PULLBASE_ADMIN_TOKEN` to avoid repeating `--admin-token` on every command:

  ```bash theme={null}
  export PULLBASE_ADMIN_TOKEN=$(pullbasectl auth login ... | jq -r '.access_token')
  ```
</Tip>

## Authentication commands

### `pullbasectl auth bootstrap-admin`

Initializes the first admin using the one-time bootstrap secret.

<ParamField flag="--server-url" type="string" required>
  URL of the Pullbase API.
</ParamField>

<ParamField flag="--bootstrap-secret" type="string">
  Secret value provided by the container. Mutually exclusive with `--bootstrap-secret-file`.
</ParamField>

<ParamField flag="--bootstrap-secret-file" type="path">
  Path to a file containing the bootstrap secret. Use when running inside a container.
</ParamField>

<ParamField flag="--username" type="string" required>
  Username for the new admin (3-64 characters, alphanumeric with `.`, `_`, `-`).
</ParamField>

<ParamField flag="--password" type="string" required>
  Password for the new admin (minimum 12 characters).
</ParamField>

<RequestExample>
  ```bash theme={null}
  pullbasectl auth bootstrap-admin \
    --server-url http://localhost:8080 \
    --bootstrap-secret-file /app/secrets/bootstrap.secret \
    --username admin_user \
    --password 'ChangeMeNow123!'
  ```
</RequestExample>

<ResponseExample>
  ```text theme={null}
  Admin bootstrap completed successfully.
  Username: admin_user
  Access token (store securely):
  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
  ```
</ResponseExample>

### `pullbasectl auth login`

Exchange a username and password for an admin JWT.

```bash theme={null}
pullbasectl auth login \
  --server-url http://localhost:8080 \
  --username admin_user \
  --password 'ChangeMeNow123!'
```

Use the returned token for subsequent CLI calls with `--admin-token`.

## Server commands

Manage servers (agents) registered with Pullbase.

### `pullbasectl servers list`

List all servers, optionally filtered by environment.

<ParamField flag="--environment-id" type="integer">
  Filter servers by environment ID.
</ParamField>

<ParamField flag="--output" type="string" default="table">
  Output format: `table` or `json`.
</ParamField>

```bash theme={null}
pullbasectl servers list \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT
```

<ResponseExample>
  ```
  ID          NAME              ENVIRONMENT    STATUS     DRIFTED  AUTO-RECONCILE
  web-01      Production Web    production     Applied    no       yes
  api-01      API Server        production     Applied    no       yes
  staging-01  Staging Server    staging        Drifted    yes      no
  ```
</ResponseExample>

Filter by environment:

```bash theme={null}
pullbasectl servers list \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --environment-id 1
```

### `pullbasectl servers create`

Register a new server.

<ParamField flag="--id" type="string" required>
  Unique server identifier (e.g., `web-01`, `api-prod-1`).
</ParamField>

<ParamField flag="--name" type="string" required>
  Human-readable server name.
</ParamField>

<ParamField flag="--environment-id" type="integer">
  Environment ID to associate with this server.
</ParamField>

<ParamField flag="--output" type="string" default="table">
  Output format: `table` or `json`.
</ParamField>

```bash theme={null}
pullbasectl servers create \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --id web-02 \
  --name "Production Web 2" \
  --environment-id 1
```

<ResponseExample>
  ```text theme={null}
  Server created successfully.
    ID:            web-02
    Name:          Production Web 2
    Environment:   1
    Auto-Reconcile: false
  ```
</ResponseExample>

### `pullbasectl servers get`

Get detailed information about a specific server.

<ParamField flag="--id" type="string" required>
  Server ID to retrieve.
</ParamField>

<ParamField flag="--output" type="string" default="table">
  Output format: `table` or `json`.
</ParamField>

```bash theme={null}
pullbasectl servers get \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --id web-01
```

<ResponseExample>
  ```text theme={null}
  Server: web-01
    Name:           Production Web
    Environment:    production
    Auto-Reconcile: true
    Status:         Applied
    Commit:         a1b2c3d
    Drifted:        no
    Last Seen:      2025-01-15T12:30:00Z
    Created:        2025-01-01T09:00:00Z
  ```
</ResponseExample>

### `pullbasectl servers delete`

Delete a server registration.

<ParamField flag="--id" type="string" required>
  Server ID to delete.
</ParamField>

<ParamField flag="--force" type="boolean" default="false">
  Skip confirmation prompt.
</ParamField>

<Note>
  Non-interactive stdin (piped/CI) requires `--force`; otherwise deletion is blocked to prevent accidental removal.
</Note>

```bash theme={null}
pullbasectl servers delete \

  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --id web-02 \
  --force
```

<ResponseExample>
  ```text theme={null}
  Server 'web-02' deleted successfully.
  ```
</ResponseExample>

### `pullbasectl servers install-script`

Generate a one-liner install script for deploying the agent to a server.

<ParamField flag="--id" type="string" required>
  Server ID.
</ParamField>

<ParamField flag="--token" type="string" required>
  Agent token for authentication (from `tokens create`).
</ParamField>

<ParamField flag="--version" type="string" default="latest">
  Agent version to install. Omitted from the request when set to `latest`.
</ParamField>

```bash theme={null}
pullbasectl servers install-script \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --id web-01 \
  --token pbt_9BFzQYxK...
```

The output is a shell script you can pipe directly to bash on the target server:

```bash theme={null}
pullbasectl servers install-script ... | ssh user@server 'sudo bash'
```

## Environment commands

Manage environments (Git repositories) that Pullbase tracks.

### `pullbasectl environments list`

List all environments.

<ParamField flag="--output" type="string" default="table">
  Output format: `table` or `json`.
</ParamField>

```bash theme={null}
pullbasectl environments list \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT
```

<ResponseExample>
  ```
  ID  NAME        REPO                                     BRANCH  STATUS  AUTO-RECONCILE
  1   production  https://github.com/acme/infra-config     main    active  yes
  2   staging     https://github.com/acme/infra-config     staging active  no
  ```
</ResponseExample>

### `pullbasectl environments create`

Create a new environment.

<ParamField flag="--name" type="string" required>
  Environment name.
</ParamField>

<ParamField flag="--repo-url" type="string" required>
  Git repository URL.
</ParamField>

<ParamField flag="--branch" type="string" default="main">
  Git branch to track.
</ParamField>

<ParamField flag="--deploy-path" type="string">
  Path within the repository where config files are located.
</ParamField>

<ParamField flag="--installation-id" type="integer">
  GitHub App installation ID (required for private repos).
</ParamField>

<ParamField flag="--output" type="string" default="table">
  Output format: `table` or `json`.
</ParamField>

```bash theme={null}
pullbasectl environments create \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --name production \
  --repo-url https://github.com/acme/infra-config \
  --branch main \
  --deploy-path configs/production
```

<ResponseExample>
  ```text theme={null}
  Environment created successfully.
    ID:            1
    Name:          production
    Repository:    https://github.com/acme/infra-config
    Branch:        main
    Deploy Path:   configs/production
    Status:        pending
    Auto-Reconcile: false
  ```
</ResponseExample>

### `pullbasectl environments get`

Get detailed information about an environment.

<ParamField flag="--id" type="integer" required>
  Environment ID to retrieve.
</ParamField>

<ParamField flag="--output" type="string" default="table">
  Output format: `table` or `json`.
</ParamField>

```bash theme={null}
pullbasectl environments get \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --id 1
```

<ResponseExample>
  ```text theme={null}
  Environment: production (ID: 1)
    Repository:     https://github.com/acme/infra-config
    Branch:         main
    Deploy Path:    configs/production
    Provider:       github
    Installation:   12345678
    Status:         active
    Auto-Reconcile: true
    Deployed:       a1b2c3d4e5f6
    Last Webhook:   2025-01-15T12:00:00Z
    Created:        2025-01-01T09:00:00Z
    Updated:        2025-01-15T12:00:00Z
  ```
</ResponseExample>

### `pullbasectl environments delete`

Delete an environment. This will affect all associated servers.

<ParamField flag="--id" type="integer" required>
  Environment ID to delete.
</ParamField>

<ParamField flag="--force" type="boolean" default="false">
  Skip confirmation prompt.
</ParamField>

```bash theme={null}
pullbasectl environments delete \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --id 2 \
  --force
```

<ResponseExample>
  ```text theme={null}
  Environment 2 deleted successfully.
  ```
</ResponseExample>

### `pullbasectl environments rollback`

Initiate a rollback to a previous commit.

<ParamField flag="--id" type="integer" required>
  Environment ID.
</ParamField>

<ParamField flag="--commit" type="string" required>
  Target commit hash to rollback to.
</ParamField>

<ParamField flag="--reason" type="string">
  Reason for the rollback (for audit purposes).
</ParamField>

<ParamField flag="--output" type="string" default="table">
  Output format: `table` or `json`.
</ParamField>

```bash theme={null}
pullbasectl environments rollback \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --id 1 \
  --commit a1b2c3d \
  --reason "Reverting broken nginx config"
```

<ResponseExample>
  ```text theme={null}
  Rollback initiated successfully.
    ID:          42
    Environment: 1
    From:        f6e5d4c
    To:          a1b2c3d
    Status:      pending
    Reason:      Reverting broken nginx config
  ```
</ResponseExample>

### `pullbasectl environments rollback-list`

List rollback history for an environment.

<ParamField flag="--id" type="integer" required>
  Environment ID.
</ParamField>

<ParamField flag="--output" type="string" default="table">
  Output format: `table` or `json`.
</ParamField>

```bash theme={null}
pullbasectl environments rollback-list \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --id 1
```

<ResponseExample>
  ```
  ID  FROM     TO       STATUS     CREATED
  42  f6e5d4c  a1b2c3d  completed  2025-01-15T12:30:00Z
  38  b2c3d4e  f6e5d4c  completed  2025-01-10T09:15:00Z
  ```
</ResponseExample>

## Status commands

View fleet-wide or per-server status.

### `pullbasectl status`

Display server status. Requires one of `--server-id`, `--environment-id`, or `--all`.

<ParamField flag="--server-id" type="string">
  Show status for a specific server.
</ParamField>

<ParamField flag="--environment-id" type="integer">
  Show status for all servers in an environment.
</ParamField>

<ParamField flag="--all" type="boolean">
  Show fleet-wide status overview.
</ParamField>

<ParamField flag="--output" type="string" default="table">
  Output format: `table` or `json`.
</ParamField>

<ParamField flag="--watch" type="boolean" default="false">
  Continuously refresh status.
</ParamField>

<ParamField flag="--interval" type="integer" default="5">
  Refresh interval in seconds (with `--watch`).
</ParamField>

**Single server status:**

```bash theme={null}
pullbasectl status \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --server-id web-01
```

**Environment status:**

```bash theme={null}
pullbasectl status \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --environment-id 1
```

**Fleet-wide status:**

```bash theme={null}
pullbasectl status \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --all
```

<ResponseExample>
  ```
  Fleet Status Summary
    Total:   5 servers
    Healthy: 4
    Drifted: 1
    Errors:  0
    Unknown: 0

  SERVER      ENVIRONMENT  STATUS   DRIFTED  COMMIT   LAST SEEN
  web-01      production   Applied  no       a1b2c3d  2 minutes ago
  web-02      production   Applied  no       a1b2c3d  1 minute ago
  api-01      production   Applied  no       a1b2c3d  3 minutes ago
  staging-01  staging      Drifted  yes      b2c3d4e  5 minutes ago
  dev-01      development  Applied  no       c3d4e5f  just now
  ```
</ResponseExample>

**Watch mode (live refresh):**

```bash theme={null}
pullbasectl status \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --all \
  --watch \
  --interval 10
```

This clears the screen and refreshes status every 10 seconds. Press `Ctrl+C` to stop.

## Config validation

### `pullbasectl validate-config`

Validate a `config.yaml` file before deploying to your Git repository.

<Tip>
  This command performs local validation only and does not require a connection to the Pullbase server. You can use it in CI pipelines or pre-commit hooks without authentication.
</Tip>

<ParamField flag="--file" type="path" required>
  Path to the config.yaml file to validate.
</ParamField>

<ParamField flag="--output" type="string" default="table">
  Output format: `table` or `json`.
</ParamField>

```bash theme={null}
pullbasectl validate-config --file ./config.yaml
```

<ResponseExample>
  ```text theme={null}
  ✓ Config is valid
  ```
</ResponseExample>

If validation fails:

```bash theme={null}
pullbasectl validate-config --file ./broken-config.yaml
```

<ResponseExample>
  ```
  ✗ Config has 2 error(s):

  FIELD              LINE  MESSAGE
  files[0].path      5     path is required
  files[1].content   12    content cannot be empty when source is not specified
  ```
</ResponseExample>

Use `--output json` for programmatic parsing:

```bash theme={null}
pullbasectl validate-config --file ./config.yaml --output json
```

## GitHub App commands

### `pullbasectl github-app bootstrap`

Validates GitHub App credentials locally and, when combined with `--server-url`, registers an environment.

Key flags:

* `--app-id`, `--private-key`, `--installation-id`, `--repository-id`, `--app-slug`
* `--server-url`, `--admin-token` (optional) to create the environment in Pullbase
* `--environment-name`, `--repo-url`, `--branch`, `--deploy-path`

### `pullbasectl github-app status`

Retrieve the GitHub App status for an environment:

```bash theme={null}
pullbasectl github-app status \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --environment-id 5
```

## Agent token commands

### `pullbasectl tokens list`

List agent tokens for a server.

```bash theme={null}
pullbasectl tokens list \
  --server-url http://localhost:8080 \
  --server-id web-01 \
  --admin-token $ADMIN_JWT
```

Output format:

```
ID	Description	Created	Expires	Last Used	Active
1	initial	2025-01-15T12:00:00Z	-	2025-01-15T12:30:00Z	true
```

### `pullbasectl tokens create`

Create an agent token.

<ParamField flag="--server-id" type="string" required>
  Server identifier.
</ParamField>

<ParamField flag="--description" type="string" required>
  Token description (e.g., "ansible integration").
</ParamField>

<ParamField flag="--expires-in" type="integer">
  Optional expiration in days.
</ParamField>

```bash theme={null}
pullbasectl tokens create \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --server-id web-01 \
  --description "blue-green deployment" \
  --expires-in 30
```

<ResponseExample>
  ```text theme={null}
  Token created successfully. Store this value securely:
  pbt_9BFzQYxK...

  Installation instructions:
  Configure AGENT_TOKEN with this value when deploying the agent.
  ```
</ResponseExample>

### `pullbasectl tokens revoke`

Deactivate a token by ID.

<ParamField flag="--server-id" type="string" required>
  Server identifier.
</ParamField>

<ParamField flag="--token-id" type="integer" required>
  Token ID to revoke.
</ParamField>

```bash theme={null}
pullbasectl tokens revoke \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --server-id web-01 \
  --token-id 17
```

## User commands

### `pullbasectl users create`

Create a new user.

<ParamField flag="--new-username" type="string" required>
  Username for the new user (3-64 characters).
</ParamField>

<ParamField flag="--new-password" type="string" required>
  Password for the new user (minimum 12 characters).
</ParamField>

<ParamField flag="--new-password-file" type="path">
  Path to file containing the new user password (alternative to `--new-password`).
</ParamField>

<ParamField flag="--role" type="string" default="user">
  Role for the new user (`admin`, `user`, or `viewer`).
</ParamField>

```bash theme={null}
pullbasectl users create \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --new-username ops_user \
  --new-password 'VerySecurePass!2024' \
  --role viewer
```

### `pullbasectl users list`

Paginate through active users.

<ParamField flag="--role" type="string">
  Filter by role (`admin`, `user`, or `viewer`).
</ParamField>

<ParamField flag="--limit" type="integer" default="100">
  Maximum users to return (1-500).
</ParamField>

<ParamField flag="--offset" type="integer" default="0">
  Pagination offset.
</ParamField>

```bash theme={null}
pullbasectl users list \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --role admin \
  --limit 50
```

### `pullbasectl users delete`

Delete a user account.

<ParamField flag="--user-id" type="integer" required>
  ID of the user to delete.
</ParamField>

<ParamField flag="--delete-acct-username" type="string" required>
  Username of the account to delete (used as confirmation).
</ParamField>

<Note>
  Deletion is blocked if you attempt to delete the last active admin or your own account. The `--delete-acct-username` flag serves as confirmation and must match the username associated with the user ID.
</Note>

```bash theme={null}
pullbasectl users delete \
  --server-url http://localhost:8080 \
  --admin-token $ADMIN_JWT \
  --user-id 7 \
  --delete-acct-username "SomeAccount123"
```

## Bootstrap wizard (interactive)

`pullbasectl bootstrap wizard` guides you through first-run setup, including admin creation and GitHub App configuration. The wizard prompts for values interactively and saves them to the server via the API.

```bash theme={null}
pullbasectl bootstrap wizard
```
