Question: How to: External Endpoints

Answer:
Unlike regular endpoints, external endpoints are not monitored by Gatus, but they are instead pushed programmatically.
This allows you to monitor anything you want, even when what you want to check lives in an environment that would not normally be accessible by Gatus.

For instance:
- You can create your own agent that lives in a private network and pushes the status of your services to a publicly-exposed Gatus instance
- You can monitor services that are not supported by Gatus
- You can implement your own monitoring system while using Gatus as the dashboard

| Parameter                                 | Description                                                                                | Default        |
|:------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------|:---------------|
| `external-endpoints`                      | List of endpoints to monitor.                                                                                | `[]`           |
| `external-endpoints[].enabled`            | Whether to monitor the endpoint.                                                                                | `true`         |
| `external-endpoints[].name`               | Name of the endpoint. Can be anything.                                                                                | Required `""`  |
| `external-endpoints[].group`              | Group name. Used to group multiple endpoints together on the dashboard.
See [Endpoint groups](#endpoint-groups).            | `""`           |
| `external-endpoints[].token`              | Bearer token required to push status to.                                                                                | Required `""`  |
| `external-endpoints[].alerts`             | List of all alerts for a given endpoint.
See [Alerting](#alerting).                                                         | `[]`           |
| `external-endpoints[].heartbeat`          | Heartbeat configuration for monitoring when the external endpoint stops sending updates.                                          | `{}`           |
| `external-endpoints[].heartbeat.interval` | Expected interval between updates. If no update is received within this interval, alerts will be triggered. Must be at least 10s. | `0` (disabled) |

Example:
```yaml
external-endpoints:
  - name: ext-ep-test
    group: core
    token: "potato"
    heartbeat:
      interval: 30m  # Automatically create a failure if no update is received within 30 minutes
    alerts:
      - type: discord
        description: "healthcheck failed"
        send-on-resolved: true
```

To push the status of an external endpoint, you can use [gatus-cli](https://github.com/TwiN/gatus-cli):
```
gatus-cli external-endpoint push --url https://status.example.org --key "core_ext-ep-test" --token "potato" --success
```

or send an HTTP request:
```
POST /api/v1/endpoints/{key}/external?success={success}&error={error}&duration={duration}
```
Where:
- `{key}` has the pattern `
_
` in which both variables have ` `, `/`, `_`, `,`, `.`, `#`, `+` and `&` replaced by `-`.
  - Using the example configuration above, the key would be `core_ext-ep-test`.
- `{success}` is a boolean (`true` or `false`) value indicating whether the health check was successful or not.
- `{error}` (optional): a string describing the reason for a failed health check. If {success} is false, this should contain the error message; if the check is successful, this will be ignored.
- `{duration}` (optional): the time that the request took as a duration string (e.g. 10s).

You must also pass the token as a `Bearer` token in the `Authorization` header.


Question: How to: Suites (ALPHA)

Answer:
Suites are collections of endpoints that are executed sequentially with a shared context.
This allows you to create complex monitoring scenarios where the result from one endpoint can be used in subsequent endpoints, enabling workflow-style monitoring.

Here are a few cases in which suites could be useful:
- Testing multi-step authentication flows (login -> access protected resource -> logout)
- API workflows where you need to chain requests (create resource -> update -> verify -> delete)
- Monitoring business processes that span multiple services
- Validating data consistency across multiple endpoints

| Parameter                         | Description                                                                                | Default       |
|:----------------------------------|:----------------------------------------------------------------------------------------------------|:--------------|
| `suites`                          | List of suites to monitor.                                                                          | `[]`          |
| `suites[].enabled`                | Whether to monitor the suite.                                                                       | `true`        |
| `suites[].name`                   | Name of the suite. Must be unique.                                                                  | Required `""` |
| `suites[].group`                  | Group name. Used to group multiple suites together on the dashboard.                                | `""`          |
| `suites[].interval`               | Duration to wait between suite executions.                                                          | `10m`         |
| `suites[].timeout`                | Maximum duration for the entire suite execution.                                                    | `5m`          |
| `suites[].context`                | Initial context values that can be referenced by endpoints.                                         | `{}`          |
| `suites[].endpoints`              | List of endpoints to execute sequentially.                                                          | Required `[]` |
| `suites[].endpoints[].store`      | Map of values to extract from the response and store in the suite context (stored even on failure). | `{}`          |
| `suites[].endpoints[].always-run` | Whether to execute this endpoint even if previous endpoints in the suite failed.                    | `false`       |

**Note**: Suite-level alerts are not supported yet. Configure alerts on individual endpoints within the suite instead.

#### Using Context in Endpoints
Once values are stored in the context, they can be referenced in subsequent endpoints:
- In the URL: `https://api.example.com/users/[CONTEXT].user_id`
- In headers: `Authorization: Bearer [CONTEXT].auth_token`
- In the body: `{"user_id": "[CONTEXT].user_id"}`
- In conditions: `[BODY].server_ip == [CONTEXT].server_ip`

Note that context/store keys are limited to A-Z, a-z, 0-9, underscores (`_`), and hyphens (`-`).

#### Example Suite Configuration
```yaml
suites:
  - name: item-crud-workflow
    group: api-tests
    interval: 5m
    context:
      price: "19.99"  # Initial static value in context
    endpoints:
      # Step 1: Create an item and store the item ID
      - name: create-item
        url: https://api.example.com/items
        method: POST
        body: '{"name": "Test Item", "price": "[CONTEXT].price"}'
        conditions:
          - "[STATUS] == 201"
          - "len([BODY].id) > 0"
          - "[BODY].price == [CONTEXT].price"
        store:
          itemId: "[BODY].id"
        alerts:
          - type: slack
            description: "Failed to create item"

      # Step 2: Update the item using the stored item ID
      - name: update-item
        url: https://api.example.com/items/[CONTEXT].itemId
        method: PUT
        body: '{"price": "24.99"}'
        conditions:
          - "[STATUS] == 200"
        alerts:
          - type: slack
            description: "Failed to update item"

      # Step 3: Fetch the item and validate the price
      - name: get-item
        url: https://api.example.com/items/[CONTEXT].itemId
        method: GET
        conditions:
          - "[STATUS] == 200"
          - "[BODY].price == 24.99"
        alerts:
          - type: slack
            description: "Item price did not update correctly"

      # Step 4: Delete the item (always-run: true to ensure cleanup even if step 2 or 3 fails)
      - name: delete-item
        url: https://api.example.com/items/[CONTEXT].itemId
        method: DELETE
        always-run: true
        conditions:
          - "[STATUS] == 204"
        alerts:
          - type: slack
            description: "Failed to delete item"
```

The suite will be considered successful only if all required endpoints pass their conditions.


Question: How to: Conditions

Answer:
Here are some examples of conditions you can use:

| Condition                        | Description                                         | Passing values             | Failing values   |
|:---------------------------------|:----------------------------------------------------|:---------------------------|------------------|
| `[STATUS] == 200`                | Status must be equal to 200                         | 200                        | 201, 404, ...    |
| `[STATUS] < 300`                 | Status must lower than 300                          | 200, 201, 299              | 301, 302, ...    |
| `[STATUS] <= 299`                | Status must be less than or equal to 299            | 200, 201, 299              | 301, 302, ...    |
| `[STATUS] > 400`                 | Status must be greater than 400                     | 401, 402, 403, 404         | 400, 200, ...    |
| `[STATUS] == any(200, 429)`      | Status must be either 200 or 429                    | 200, 429                   | 201, 400, ...    |
| `[CONNECTED] == true`            | Connection to host must've been successful          | true                       | false            |
| `[RESPONSE_TIME] < 500`          | Response time must be below 500ms                   | 100ms, 200ms, 300ms        | 500ms, 501ms     |
| `[IP] == 127.0.0.1`              | Target IP must be 127.0.0.1                         | 127.0.0.1                  | 0.0.0.0          |
| `[BODY] == 1`                    | The body must be equal to 1                         | 1                          | `{}`, `2`, ...   |
| `[BODY].user.name == john`       | JSONPath value of `$.user.name` is equal to `john`  | `{"user":{"name":"john"}}` |                  |
| `[BODY].data[0].id == 1`         | JSONPath value of `$.data[0].id` is equal to 1      | `{"data":[{"id":1}]}`      |                  |
| `[BODY].age == [BODY].id`        | JSONPath value of `$.age` is equal JSONPath `$.id`  | `{"age":1,"id":1}`         |                  |
| `len([BODY].data) < 5`           | Array at JSONPath `$.data` has less than 5 elements | `{"data":[{"id":1}]}`      |                  |
| `len([BODY].name) == 8`          | String at JSONPath `$.name` has a length of 8       | `{"name":"john.doe"}`      | `{"name":"bob"}` |
| `has([BODY].errors) == false`    | JSONPath `$.errors` does not exist                  | `{"name":"john.doe"}`      | `{"errors":[]}`  |
| `has([BODY].users) == true`      | JSONPath `$.users` exists                           | `{"users":[]}`             | `{}`             |
| `[BODY].name == pat(john*)`      | String at JSONPath `$.name` matches pattern `john*` | `{"name":"john.doe"}`      | `{"name":"bob"}` |
| `[BODY].id == any(1, 2)`         | Value at JSONPath `$.id` is equal to `1` or `2`     | 1, 2                       | 3, 4, 5          |
| `[CERTIFICATE_EXPIRATION] > 48h` | Certificate expiration is more than 48h away        | 49h, 50h, 123h             | 1h, 24h, ...     |
| `[DOMAIN_EXPIRATION] > 720h`     | The domain must expire in more than 720h            | 4000h                      | 1h, 24h, ...     |

#### Placeholders
| Placeholder                | Description                                                                               | Example of resolved value                    |
|:---------------------------|:------------------------------------------------------------------------------------------|:---------------------------------------------|
| `[STATUS]`                 | Resolves into the HTTP status of the request                                              | `404`                                        |
| `[RESPONSE_TIME]`          | Resolves into the response time the request took, in ms                                   | `10`                                         |
| `[IP]`                     | Resolves into the IP of the target host                                                   | `192.168.0.232`                              |
| `[BODY]`                   | Resolves into the response body. Supports JSONPath.                                       | `{"name":"john.doe"}`                        |
| `[CONNECTED]`              | Resolves into whether a connection could be established                                   | `true`                                       |
| `[CERTIFICATE_EXPIRATION]` | Resolves into the duration before certificate expiration (valid units are "s", "m", "h".) | `24h`, `48h`, 0 (if not protocol with certs) |
| `[DOMAIN_EXPIRATION]`      | Resolves into the duration before the domain expires (valid units are "s", "m", "h".)     | `24h`, `48h`, `1234h56m78s`                  |
| `[DNS_RCODE]`              | Resolves into the DNS status of the response                                              | `NOERROR`                                    |

#### Functions
| Function | Description


Question: How to: Announcements

Answer:
System-wide announcements allow you to display important messages at the top of the status page. These can be used to inform users about planned maintenance, ongoing issues, or general information. You can use markdown to format your announcements.

This is essentially what some status page calls "incident communications".

| Parameter                   | Description                                                                                | Default  |
|:----------------------------|:-------------------------------------------------------------------------------------------------------------------------|:---------|
| `announcements`             | List of announcements to display                                                                                | `[]`     |
| `announcements[].timestamp` | UTC timestamp when the announcement was made (RFC3339 format)                                                            | Required |
| `announcements[].type`      | Type of announcement. Valid values: `outage`, `warning`, `information`, `operational`, `none`                            | `"none"` |
| `announcements[].message`   | The message to display to users                                                                                | Required |
| `announcements[].archived`  | Whether to archive the announcement. Archived announcements show at the bottom of the status page instead of at the top. | `false`  |

Types:
- **outage**: Indicates service disruptions or critical issues (red theme)
- **warning**: Indicates potential issues or important notices (yellow theme)
- **information**: General information or updates (blue theme)
- **operational**: Indicates resolved issues or normal operations (green theme)
- **none**: Neutral announcements with no specific severity (gray theme, default if none are specified)

Example Configuration:
```yaml
announcements:
  - timestamp: 2025-11-07T14:00:00Z
    type: outage
    message: "Scheduled maintenance on database servers from 14:00 to 16:00 UTC"
  - timestamp: 2025-11-07T16:15:00Z
    type: operational
    message: "Database maintenance completed successfully. All systems operational."
  - timestamp: 2025-11-07T12:00:00Z
    type: information
    message: "New monitoring dashboard features will be deployed next week"
  - timestamp: 2025-11-06T09:00:00Z
    type: warning
    message: "Elevated API response times observed for US customers"
    archived: true
```

If at least one announcement is archived, a **Past Announcements** section will be rendered at the bottom of the status page:
![Gatus past announcements section](.github/assets/past-announcements.jpg)


Question: How to: Because the data is stored in memory, the data will not survive a restart.

Answer:
storage:
  type: memory
  maximum-number-of-results: 200
  maximum-number-of-events: 5
```
- If `storage.type` is `sqlite`, `storage.path` must not be blank:
```yaml
storage:
  type: sqlite
  path: data.db
```
See [examples/docker-compose-sqlite-storage](.examples/docker-compose-sqlite-storage) for an example.

- If `storage.type` is `postgres`, `storage.path` must be the connection URL:
```yaml
storage:
  type: postgres
  path: "postgres://user:password@127.0.0.1:5432/gatus?sslmode=disable"
```
See [examples/docker-compose-postgres-storage](.examples/docker-compose-postgres-storage) for an example.


Question: How to: Maintenance

Answer:
If you have maintenance windows, you may not want to be annoyed by alerts.
To do that, you'll have to use the maintenance configuration:

| Parameter              | Description                                                                                | Default       |
|:-----------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------|
| `maintenance.enabled`  | Whether the maintenance period is enabled                                                                                | `true`        |
| `maintenance.start`    | Time at which the maintenance window starts in `hh:mm` format (e.g. `23:00`)                                                                                | Required `""` |
| `maintenance.duration` | Duration of the maintenance window (e.g. `1h`, `30m`)                                                                                | Required `""` |
| `maintenance.timezone` | Timezone of the maintenance window format (e.g. `Europe/Amsterdam`).
See [List of tz database time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for more info | `UTC`         |
| `maintenance.every`    | Days on which the maintenance period applies (e.g. `[Monday, Thursday]`).
If left empty, the maintenance window applies every day                                                     | `[]`          |

Here's an example:
```yaml
maintenance:
  start: 23:00
  duration: 1h
  timezone: "Europe/Amsterdam"
  every: [Monday, Thursday]
```
Note that you can also specify each day on separate lines:
```yaml
maintenance:
  start: 23:00
  duration: 1h
  timezone: "Europe/Amsterdam"
  every:
    - Monday
    - Thursday
```
You can also specify maintenance windows on a per-endpoint basis:
```yaml
endpoints:
  - name: endpoint-1
    url: "https://example.org"
    maintenance-windows:
      - start: "07:30"
        duration: 40m
        timezone: "Europe/Berlin"
      - start: "14:30"
        duration: 1h
        timezone: "Europe/Berlin"
```


Question: How to: TLS Encryption

Answer:
Gatus supports basic encryption with TLS. To enable this, certificate files in PEM format have to be provided.

The example below shows an example configuration which makes gatus respond on port 4443 to HTTPS requests:
```yaml
web:
  port: 4443
  tls:
    certificate-file: "certificate.crt"
    private-key-file: "private.key"
```


Question: How to: Connectivity

Answer:
| Parameter                       | Description                                | Default       |
|:--------------------------------|:-------------------------------------------|:--------------|
| `connectivity`                  | Connectivity configuration                 | `{}`          |
| `connectivity.checker`          | Connectivity checker configuration         | Required `{}` |
| `connectivity.checker.target`   | Host to use for validating connectivity    | Required `""` |
| `connectivity.checker.interval` | Interval at which to validate connectivity | `1m`          |

While Gatus is used to monitor other services, it is possible for Gatus itself to lose connectivity to the internet.
In order to prevent Gatus from reporting endpoints as unhealthy when Gatus itself is unhealthy, you may configure
Gatus to periodically check for internet connectivity.

All endpoint executions are skipped while the connectivity checker deems connectivity to be down.

```yaml
connectivity:
  checker:
    target: 1.1.1.1:53
    interval: 60s
```


Question: How to: Remote instances (EXPERIMENTAL)

Answer:
This feature allows you to retrieve endpoint statuses from a remote Gatus instance.

There are two main use cases for this:
- You have multiple Gatus instances running on different machines, and you wish to visually expose the statuses through a single dashboard
- You have one or more Gatus instances that are not publicly accessible (e.g. behind a firewall), and you wish to retrieve

This is an experimental feature. It may be removed or updated in a breaking manner at any time. Furthermore,
there are known issues with this feature. If you'd like to provide some feedback, please write a comment in [#64](https://github.com/TwiN/gatus/issues/64).
Use at your own risk.

| Parameter                          | Description                                  | Default       |
|:-----------------------------------|:---------------------------------------------|:--------------|
| `remote`                           | Remote configuration                         | `{}`          |
| `remote.instances`                 | List of remote instances                     | Required `[]` |
| `remote.instances.endpoint-prefix` | String to prefix all endpoint names with     | `""`          |
| `remote.instances.url`             | URL from which to retrieve endpoint statuses | Required `""` |

```yaml
remote:
  instances:
    - endpoint-prefix: "status.example.org-"
      url: "https://status.example.org/api/v1/endpoints/statuses"
```


Question: How to: Deployment

Answer: Many examples can be found in the [.examples](.examples) folder, but this section will focus on the most popular ways of deploying Gatus.


Question: How to: Helm Chart

Answer:
[Helm](https://helm.sh) must be installed to use the chart.
Please refer to Helm's [documentation](https://helm.sh/docs/) to get started.

Once Helm is set up properly, add the repository as follows:

```console
helm repo add twin https://twin.github.io/helm-charts
helm repo update
helm install gatus twin/gatus
```

To get more details, please check [chart's configuration](https://github.com/TwiN/helm-charts/blob/master/charts/gatus/README.md).


Question: How to: Sending a GraphQL request

Answer:
By setting `endpoints[].graphql` to true, the body will automatically be wrapped by the standard GraphQL `query` parameter.

For instance, the following configuration:
```yaml
endpoints:
  - name: filter-users-by-gender
    url: http://localhost:8080/playground
    method: POST
    graphql: true
    body: |
      {
        users(gender: "female") {
          id
          name
          gender
          avatar
        }
      }
    conditions:
      - "[STATUS] == 200"
      - "[BODY].data.users[0].gender == female"
```

will send a `POST` request to `http://localhost:8080/playground` with the following body:
```json
{"query":"      {\n        users(gender: \"female\") {\n          id\n          name\n          gender\n          avatar\n        }\n      }"}
```


Question: How to: Recommended interval

Answer:
To ensure that Gatus provides reliable and accurate results (i.e. response time), Gatus limits the number of
endpoints/suites that can be evaluated at the same time.
In other words, even if you have multiple endpoints with the same interval, they are not guaranteed to run at the same time.

The number of concurrent evaluations is determined by the `concurrency` configuration parameter, which defaults to `3`.

You can test this yourself by running Gatus with several endpoints configured with a very short, unrealistic interval,
such as 1ms. You'll notice that the response time does not fluctuate - that is because while endpoints are evaluated on
different goroutines, there's a semaphore that controls how many endpoints/suites from running at the same time.

Unfortunately, there is a drawback. If you have a lot of endpoints, including some that are very slow or prone to timing out
(the default timeout is 10s), those slow evaluations may prevent other endpoints/suites from being evaluated.

The interval does not include the duration of the request itself, which means that if an endpoint has an interval of 30s
and the request takes 2s to complete, the timestamp between two evaluations will be 32s, not 30s.

While this does not prevent Gatus' from performing health checks on all other endpoints, it may cause Gatus to be unable
to respect the configured interval, for instance, assuming `concurrency` is set to `1`:
- Endpoint A has an interval of 5s, and times out after 10s to complete
- Endpoint B has an interval of 5s, and takes 1ms to complete
- Endpoint B will be unable to run every 5s, because endpoint A's health evaluation takes longer than its interval

To sum it up, while Gatus can handle any interval you throw at it, you're better off having slow requests with
higher interval.

As a rule of thumb, I personally set the interval for more complex health checks to `5m` (5 minutes) and
simple health checks used for alerting (PagerDuty/Twilio) to `30s`.


Question: How to: Default timeouts

Answer:
| Endpoint type | Timeout |
|:--------------|:--------|
| HTTP          | 10s     |
| TCP           | 10s     |
| ICMP          | 10s     |

To modify the timeout, see [Client configuration](#client-configuration).


Question: How to: Monitoring a TCP endpoint

Answer:
By prefixing `endpoints[].url` with `tcp://`, you can monitor TCP endpoints at a very basic level:
```yaml
endpoints:
  - name: redis
    url: "tcp://127.0.0.1:6379"
    interval: 30s
    conditions:
      - "[CONNECTED] == true"
```
If `endpoints[].body` is set then it is sent and the first 1024 bytes of the response will be in `[BODY]`.

Placeholder `[STATUS]` as well as the fields `endpoints[].headers`,
`endpoints[].method` and `endpoints[].graphql` are not supported for TCP endpoints.

This works for applications such as databases (Postgres, MySQL, etc.) and caches (Redis, Memcached, etc.).

> 📝 `[CONNECTED] == true` does not guarantee that the endpoint itself is healthy - it only guarantees that there's
> something at the given address listening to the given port, and that a connection to that address was successfully
> established.


Question: How to: Monitoring a UDP endpoint

Answer:
By prefixing `endpoints[].url` with `udp://`, you can monitor UDP endpoints at a very basic level:
```yaml
endpoints:
  - name: example
    url: "udp://example.org:80"
    conditions:
      - "[CONNECTED] == true"
```

If `endpoints[].body` is set then it is sent and the first 1024 bytes of the response will be in `[BODY]`.

Placeholder `[STATUS]` as well as the fields `endpoints[].headers`,
`endpoints[].method` and `endpoints[].graphql` are not supported for UDP endpoints.

This works for UDP based application.


Question: How to: Monitoring a SCTP endpoint

Answer:
By prefixing `endpoints[].url` with `sctp://`, you can monitor Stream Control Transmission Protocol (SCTP) endpoints at a very basic level:
```yaml
endpoints:
  - name: example
    url: "sctp://127.0.0.1:38412"
    conditions:
      - "[CONNECTED] == true"
```

Placeholders `[STATUS]` and `[BODY]` as well as the fields `endpoints[].body`, `endpoints[].headers`,
`endpoints[].method` and `endpoints[].graphql` are not supported for SCTP endpoints.

This works for SCTP based application.


Question: How to: Monitoring a WebSocket endpoint

Answer:
By prefixing `endpoints[].url` with `ws://` or `wss://`, you can monitor WebSocket endpoints:
```yaml
endpoints:
  - name: example
    url: "wss://echo.websocket.org/"
    body: "status"
    conditions:
      - "[CONNECTED] == true"
      - "[BODY] == pat(*served by*)"
```

The `[BODY]` placeholder contains the output of the query, and `[CONNECTED]`
shows whether the connection was successfully established. You can use Go template
syntax.


Question: How to: Monitoring an endpoint using gRPC

Answer:
You can monitor gRPC services by prefixing `endpoints[].url` with `grpc://` or `grpcs://`.
Gatus executes the standard `grpc.health.v1.Health/Check` RPC against the target.

```yaml
endpoints:
  - name: my-grpc
    url: grpc://localhost:50051
    interval: 30s
    conditions:
      - "[CONNECTED] == true"
      - "[BODY].status == SERVING"  # BODY is read only when referenced
    client:
      timeout: 5s
```

For TLS-enabled servers, use `grpcs://` and configure client TLS if necessary:

```yaml
endpoints:
  - name: my-grpcs
    url: grpcs://example.com:443
    conditions:
      - "[CONNECTED] == true"
      - "[BODY].status == SERVING"
    client:
      timeout: 5s
      insecure: false          # set true to skip cert verification (not recommended)
      tls:
        certificate-file: /path/to/cert.pem      # optional mTLS client cert
        private-key-file: /path/to/key.pem       # optional mTLS client key
```

Notes:
- The health check targets the default service (`service: ""`). Support for a custom service name can be added later if needed.
- The response body is exposed as a minimal JSON object like `{"status":"SERVING"}` only when required by conditions or suite store mappings.
- Timeouts, custom DNS resolvers and SSH tunnels are honored via the existing [`client` configuration](#client-configuration).


Question: How to: Monitoring an endpoint using ICMP

Answer:
By prefixing `endpoints[].url` with `icmp://`, you can monitor endpoints at a very basic level using ICMP, or more
commonly known as "ping" or "echo":
```yaml
endpoints:
  - name: ping-example
    url: "icmp://example.com"
    conditions:
      - "[CONNECTED] == true"
```

Only the placeholders `[CONNECTED]`, `[IP]` and `[RESPONSE_TIME]` are supported for endpoints of type ICMP.
You can specify a domain prefixed by `icmp://`, or an IP address prefixed by `icmp://`.

If you run Gatus on Linux, please read the Linux section on [https://github.com/prometheus-community/pro-bing#linux]
if you encounter any problems.

Prior to `v5.31.0`, some environment setups required adding `CAP_NET_RAW` capabilities to allow pings to work.
As of `v5.31.0`, this is no longer necessary, and ICMP checks will work with unprivileged pings unless running as root. See #1346 for details.


Question: How to: Monitoring an endpoint using DNS queries

Answer:
Defining a `dns` configuration in an endpoint will automatically mark said endpoint as an endpoint of type DNS:
```yaml
endpoints:
  - name: example-dns-query
    url: "8.8.8.8" # Address of the DNS server to use
    dns:
      query-name: "example.com"
      query-type: "A"
    conditions:
      - "[BODY] == 93.184.215.14"
      - "[DNS_RCODE] == NOERROR"
```

There are two placeholders that can be used in the conditions for endpoints of type DNS:
- The placeholder `[BODY]` resolves to the output of the query. For instance, a query of type `A` would return an IPv4.
- The placeholder `[DNS_RCODE]` resolves to the name associated to the response code returned by the query, such as
`NOERROR`, `FORMERR`, `SERVFAIL`, `NXDOMAIN`, etc.


Question: How to: Monitoring an endpoint using SSH


Question: How to: Monitoring an endpoint using STARTTLS

Answer:
If you have an email server that you want to ensure there are no problems with, monitoring it through STARTTLS
will serve as a good initial indicator:
```yaml
endpoints:
  - name: starttls-smtp-example
    url: "starttls://smtp.gmail.com:587"
    interval: 30m
    client:
      timeout: 5s
    conditions:
      - "[CONNECTED] == true"
      - "[CERTIFICATE_EXPIRATION] > 48h"
```


Question: How to: Monitoring an endpoint using TLS

Answer:
Monitoring endpoints using SSL/TLS encryption, such as LDAP over TLS, can help detect certificate expiration:
```yaml
endpoints:
  - name: tls-ldaps-example
    url: "tls://ldap.example.com:636"
    interval: 30m
    client:
      timeout: 5s
    conditions:
      - "[CONNECTED] == true"
      - "[CERTIFICATE_EXPIRATION] > 48h"
```

If `endpoints[].body` is set then it is sent and the first 1024 bytes of the response will be in `[BODY]`.

Placeholder `[STATUS]` as well as the fields `endpoints[].headers`,
`endpoints[].method` and `endpoints[].graphql` are not supported for TLS endpoints.


Question: How to: Monitoring domain expiration

Answer:
You can monitor the expiration of a domain with all endpoint types except for DNS by using the `[DOMAIN_EXPIRATION]`
placeholder:
```yaml
endpoints:
  - name: check-domain-and-certificate-expiration
    url: "https://example.org"
    interval: 1h
    conditions:
      - "[DOMAIN_EXPIRATION] > 720h"
      - "[CERTIFICATE_EXPIRATION] > 240h"
```

> ⚠ The usage of the `[DOMAIN_EXPIRATION]` placeholder requires Gatus to use RDAP, or as a fallback, send a request to the official IANA WHOIS service
> [through a library](https://github.com/TwiN/whois) and in some cases, a secondary request to a TLD-specific WHOIS server (e.g. `whois.nic.sh`).
> To prevent the WHOIS service from throttling your IP address if you send too many requests, Gatus will prevent you from
> using the `[DOMAIN_EXPIRATION]` placeholder on an endpoint with an interval of less than `5m`.


Question: How to: Concurrency

Answer:
By default, Gatus allows up to 5 endpoints/suites to be monitored concurrently. This provides a balance between performance and resource usage while maintaining accurate response time measurements.

You can configure the concurrency level using the `concurrency` parameter:

```yaml


Question: How to: concurrency: 3

Answer:
```

**Important considerations:**
- Higher concurrency can improve monitoring performance when you have many endpoints
- Conditions using the `[RESPONSE_TIME]` placeholder may be less accurate with very high concurrency due to system resource contention
- Set to `0` for unlimited concurrency (equivalent to the deprecated `disable-monitoring-lock: true`)

**Use cases for higher concurrency:**
- You have a large number of endpoints to monitor
- You want to monitor endpoints at very short intervals (< 5s)
- You're using Gatus for load testing scenarios

**Legacy configuration:**
The `disable-monitoring-lock` parameter is deprecated but still supported for backward compatibility. It's equivalent to setting `concurrency: 0`.


Question: How to: Reloading configuration on the fly

Answer:
For the sake of convenience, Gatus automatically reloads the configuration on the fly if the loaded configuration file
is updated while Gatus is running.

By default, the application will exit if the updating configuration is invalid, but you can configure
Gatus to continue running if the configuration file is updated with an invalid configuration by
setting `skip-invalid-config-update` to `true`.

Keep in mind that it is in your best interest to ensure the validity of the configuration file after each update you
apply to the configuration file while Gatus is running by looking at the log and making sure that you do not see the
following message:
```
The configuration file was updated, but it is not valid. The old configuration will continue being used.
```
Failure to do so may result in Gatus being unable to start if the application is restarted for whatever reason.

I recommend not setting `skip-invalid-config-update` to `true` to avoid a situation like this, but the choice is yours
to make.

**If you are not using a file storage**, updating the configuration while Gatus is running is effectively
the same as restarting the application.

> 📝 Updates may not be detected if the config file is bound instead of the config folder. See [#151](https://github.com/TwiN/gatus/issues/151).


Question: How to: Endpoint groups

Answer:
Endpoint groups are used for grouping multiple endpoints together on the dashboard.

```yaml
endpoints:
  - name: frontend
    group: core
    url: "https://example.org/"
    interval: 5m
    conditions:
      - "[STATUS] == 200"

  - name: backend
    group: core
    url: "https://example.org/"
    interval: 5m
    conditions:
      - "[STATUS] == 200"

  - name: monitoring
    group: internal
    url: "https://example.org/"
    interval: 5m
    conditions:
      - "[STATUS] == 200"

  - name: nas
    group: internal
    url: "https://example.org/"
    interval: 5m
    conditions:
      - "[STATUS] == 200"

  - name: random endpoint that is not part of a group
    url: "https://example.org/"
    interval: 5m
    conditions:
      - "[STATUS] == 200"
```

The configuration above will result in a dashboard that looks like this when sorting by group:

![Gatus Endpoint Groups](.github/assets/endpoint-groups.jpg)


Question: How to: How do I sort by group by default?

Answer:
Set `ui.default-sort-by` to `group` in the configuration file:
```yaml
ui:
  default-sort-by: group
```
Note that if a user has already sorted the dashboard by a different field, the default sort will not be applied unless the user
clears their browser's localstorage.


Question: How to: Exposing Gatus on a custom path

Answer:
Currently, you can expose the Gatus UI using a fully qualified domain name (FQDN) such as `status.example.org`. However, it does not support path-based routing, which means you cannot expose it through a URL like `example.org/status/`.

For more information, see https://github.com/TwiN/gatus/issues/88.


Question: How to: Exposing Gatus on a custom port

Answer:
By default, Gatus is exposed on port `8080`, but you may specify a different port by setting the `web.port` parameter:
```yaml
web:
  port: 8081
```

If you're using a PaaS like Heroku that doesn't let you set a custom port and exposes it through an environment
variable instead see [Use environment variables in config files](#use-environment-variables-in-config-files).


Question: How to: Use environment variables in config files

Answer:
You can use environment variables directly in the configuration file which will be substituted from the environment:
```yaml
web:
  port: ${PORT}

ui:
  title: $TITLE
```
⚠ When your configuration parameter contains a `$` symbol, you have to escape `$` with `$$`.


Question: How to: Configuring a startup delay

Answer: If, for any reason, you need Gatus to wait for a given amount of time before monitoring the endpoints on application start, you can use the `GATUS_DELAY_START_SECONDS` environment variable to make Gatus sleep on startup.


Question: How to: Keeping your configuration small

Answer:
While not specific to Gatus, you can leverage YAML anchors to create a default configuration.
If you have a large configuration file, this should help you keep things clean.
Example
```yaml
default-endpoint: &defaults
  group: core
  interval: 5m
  client:
    insecure: true
    timeout: 30s
  conditions:
    - "[STATUS] == 200"

endpoints:
  - name: anchor-example-1
    <<: *defaults               # This will merge the configuration under &defaults with this endpoint
    url: "https://example.org"

  - name: anchor-example-2
    <<: *defaults
    group: example              # This will override the group defined in &defaults
    url: "https://example.com"

  - name: anchor-example-3
    <<: *defaults
    url: "https://twin.sh/health"
    conditions:                # This will override the conditions defined in &defaults
      - "[STATUS] == 200"
      - "[BODY].status == UP"
```


Question: How to: Proxy client configuration

Answer:
You can configure a proxy for the client to use by setting the `proxy-url` parameter in the client configuration.

```yaml
endpoints:
  - name: website
    url: "https://twin.sh/health"
    client:
      proxy-url: http://proxy.example.com:8080
    conditions:
      - "[STATUS] == 200"
```


Question: How to: How to fix 431 Request Header Fields Too Large error

Answer:
Depending on where your environment is deployed and what kind of middleware or reverse proxy sits in front of Gatus,
you may run into this issue. This could be because the request headers are too large, e.g. big cookies.

By default, `web.read-buffer-size` is set to `8192`, but increasing this value like so will increase the read buffer size:
```yaml
web:
  read-buffer-size: 32768
```


Question: How to: Installing as binary

Answer:
You can download Gatus as a binary using the following command:
```
go install github.com/TwiN/gatus/v5@latest
```


Question: How to: High level design overview

Answer: ![Gatus diagram](.github/assets/gatus-diagram.jpg)


Question: How to: Precompiled binaries

Answer:
Precompiled binaries for released versions are available in the
[*download* section](https://prometheus.io/download/)
on [prometheus.io](https://prometheus.io). Using the latest production release binary
is the recommended way of installing Alertmanager.


Question: How to: Docker images

Answer:
Docker images are available on [Quay.io](https://quay.io/repository/prometheus/alertmanager) or [Docker Hub](https://hub.docker.com/r/prom/alertmanager/).

You can launch an Alertmanager container for trying it out with

    $ docker run --name alertmanager -d -p 127.0.0.1:9093:9093 quay.io/prometheus/alertmanager

Alertmanager will now be reachable at http://localhost:9093/.


Question: How to: Compiling the binary

Answer:
You can either `go install` it:

```
$ go install github.com/prometheus/alertmanager/cmd/...@latest


Question: How to: cd $GOPATH/src/github.com/prometheus/alertmanager

Answer:
$ alertmanager --config.file=
```

Or clone the repository and build manually:

```
$ mkdir -p $GOPATH/src/github.com/prometheus
$ cd $GOPATH/src/github.com/prometheus
$ git clone https://github.com/prometheus/alertmanager.git
$ cd alertmanager
$ make build
$ ./alertmanager --config.file=
```

You can also build just one of the binaries in this repo by passing a name to the build function:
```
$ make build BINARIES=amtool
```


Question: How to: The root route on which each incoming alert enters.

Answer:
route:
  # The root route must not have any matchers as it is the entry point for
  # all alerts. It needs to have a receiver configured so alerts that do not
  # match any of the sub-routes are sent to someone.
  receiver: 'team-X-mails'

  # The labels by which incoming alerts are grouped together. For example,
  # multiple alerts coming in for cluster=A and alertname=LatencyHigh would
  # be batched into a single group.
  #
  # To aggregate by all possible labels use '...' as the sole label name.
  # This effectively disables aggregation entirely, passing through all
  # alerts as-is. This is unlikely to be what you want, unless you have
  # a very low alert volume or your upstream notification system performs
  # its own grouping. Example: group_by: [...]
  group_by: ['alertname', 'cluster']

  # When a new group of alerts is created by an incoming alert, wait at
  # least 'group_wait' to send the initial notification.
  # This way ensures that you get multiple alerts for the same group that start
  # firing shortly after another are batched together on the first
  # notification.
  group_wait: 30s

  # When the first notification was sent, wait 'group_interval' to send a batch
  # of new alerts that started firing for that group.
  group_interval: 5m

  # If an alert has successfully been sent, wait 'repeat_interval' to
  # resend them.
  repeat_interval: 3h

  # All the above attributes are inherited by all child routes and can
  # overwritten on each.

  # The child route trees.
  routes:
  # This route performs a regular expression match on alert labels to
  # catch alerts that are related to a list of services.
  - matchers:
    - service=~"^(foo1|foo2|baz)$"
    receiver: team-X-mails

    # The service has a sub-route for critical alerts, any alerts
    # that do not match, i.e. severity != critical, fall-back to the
    # parent node and are sent to 'team-X-mails'
    routes:
    - matchers:
      - severity="critical"
      receiver: team-X-pager

  - matchers:
    - service="files"
    receiver: team-Y-mails

    routes:
    - matchers:
      - severity="critical"
      receiver: team-Y-pager

  # This route handles all alerts coming from a database service. If there's
  # no team to handle it, it defaults to the DB team.
  - matchers:
    - service="database"

    receiver: team-DB-pager
    # Also group alerts by affected database.
    group_by: [alertname, cluster, database]

    routes:
    - matchers:
      - owner="team-X"
      receiver: team-X-pager

    - matchers:
      - owner="team-Y"
      receiver: team-Y-pager


Question: How to: already critical.

Answer:
inhibit_rules:
- source_matchers:
    - severity="critical"
  target_matchers:
    - severity="warning"
  # Apply inhibition if the alertname is the same.
  # CAUTION:
  #   If all label names listed in `equal` are missing
  #   from both the source and target alerts,
  #   the inhibition rule will apply!
  equal: ['alertname']

receivers:
- name: 'team-X-mails'
  email_configs:
  - to: 'team-X+alerts@example.org, team-Y+alerts@example.org'

- name: 'team-X-pager'
  email_configs:
  - to: 'team-X+alerts-critical@example.org'
  pagerduty_configs:
  - routing_key:
- name: 'team-Y-mails'
  email_configs:
  - to: 'team-Y+alerts@example.org'

- name: 'team-Y-pager'
  pagerduty_configs:
  - routing_key:
- name: 'team-DB-pager'
  pagerduty_configs:
  - routing_key:
```


Question: How to: Configuration

Answer:
`amtool` allows a configuration file to specify some options for convenience. The default configuration file paths are `$HOME/.config/amtool/config.yml` or `/etc/amtool/config.yml`

An example configuration file might look like the following:

```


Question: How to: View routing tree of remote Alertmanager

Answer: $ amtool config routes --alertmanager.url=http://localhost:9090


Question: How to: Test if alert matches expected receiver

Answer:
$ amtool config routes test --config.file=doc/examples/simple.yml --tree --verify.receivers=team-X-pager service=database owner=team-X
```


Question: How to: High Availability

Answer:
Alertmanager's high availability is in production use at many companies and is enabled by default.

> Important: Both UDP and TCP are needed in alertmanager 0.15 and higher for the cluster to work.
>  - If you are using a firewall, make sure to whitelist the clustering port for both protocols.
>  - If you are running in a container, make sure to expose the clustering port for both protocols.

To create a highly available cluster of the Alertmanager the instances need to
be configured to communicate with each other. This is configured using the
`--cluster.*` flags.

- `--cluster.listen-address` string: cluster listen address (default "0.0.0.0:9094"; empty string disables HA mode)
- `--cluster.advertise-address` string: cluster advertise address
- `--cluster.peer` value: initial peers (repeat flag for each additional peer)
- `--cluster.peer-timeout` value: peer timeout period (default "15s")
- `--cluster.peers-resolve-timeout` value: peers resolve timeout period (default "15s")
- `--cluster.gossip-interval` value: cluster message propagation speed
  (default "200ms")
- `--cluster.pushpull-interval` value: lower values will increase
  convergence speeds at expense of bandwidth (default "1m0s")
- `--cluster.settle-timeout` value: maximum time to wait for cluster
  connections to settle before evaluating notifications.
- `--cluster.tcp-timeout` value: timeout value for tcp connections, reads and writes (default "10s")
- `--cluster.probe-timeout` value: time to wait for ack before marking node unhealthy
  (default "500ms")
- `--cluster.probe-interval` value: interval between random node probes (default "1s")
- `--cluster.reconnect-interval` value: interval between attempting to reconnect to lost peers (default "10s")
- `--cluster.reconnect-timeout` value: length of time to attempt to reconnect to a lost peer (default: "6h0m0s")
- `--cluster.label` value: the label is an optional string to include on each packet and stream. It uniquely identifies the cluster and prevents cross-communication issues when sending gossip messages (default:"")

The chosen port in the `cluster.listen-address` flag is the port that needs to be
specified in the `cluster.peer` flag of the other peers.

The `cluster.advertise-address` flag is required if the instance doesn't have
an IP address that is part of [RFC 6890](https://tools.ietf.org/html/rfc6890)
with a default route.

To start a cluster of three peers on your local machine use [`goreman`](https://github.com/mattn/goreman) and the
Procfile within this repository.

	goreman start

To point your Prometheus 1.4, or later, instance to multiple Alertmanagers, configure them
in your `prometheus.yml` configuration file, for example:

```yaml
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      - alertmanager1:9093
      - alertmanager2:9093
      - alertmanager3:9093
```

> Important: Do not load balance traffic between Prometheus and its Alertmanagers, but instead point Prometheus to a list of all Alertmanagers. The Alertmanager implementation expects all alerts to be sent to all Alertmanagers to ensure high availability.


Question: How to: Turn off high availability

Answer: If running Alertmanager in high availability mode is not desired, setting `--cluster.listen-address=` prevents Alertmanager from listening to incoming peer requests.


Question: How to: Contributing

Answer:
Check the [Prometheus contributing page](https://github.com/prometheus/prometheus/blob/main/CONTRIBUTING.md).

To contribute to the user interface, refer to [ui/app/CONTRIBUTING.md](ui/app/CONTRIBUTING.md).


Question: How to: Prerequisites

Answer:
You will need a Kubernetes cluster, that's it! By default it is assumed, that the kubelet uses token authentication and authorization, as otherwise Prometheus needs a client certificate, which gives it full access to the kubelet, rather than just the metrics. Token authentication and authorization allows more fine grained and easier access control.

This means the kubelet configuration must contain these flags:

* `--authentication-token-webhook=true` This flag enables, that a `ServiceAccount` token can be used to authenticate against the kubelet(s). This can also be enabled by setting the kubelet configuration value `authentication.webhook.enabled` to `true`.
* `--authorization-mode=Webhook` This flag enables, that the kubelet will perform an RBAC request with the API to determine, whether the requesting entity (Prometheus in this case) is allowed to access a resource, in specific for this project the `/metrics` endpoint. This can also be enabled by setting the kubelet configuration value `authorization.mode` to `Webhook`.

This stack provides [resource metrics](https://github.com/kubernetes/metrics#resource-metrics-api) by deploying
the [Prometheus Adapter](https://github.com/kubernetes-sigs/prometheus-adapter).
This adapter is an Extension API Server and Kubernetes needs to be have this feature enabled, otherwise the adapter has
no effect, but is still deployed.


Question: How to: Compatibility

Answer:
The following Kubernetes versions are supported and work as we test against these versions in their respective branches. But note that other versions might work!

> [!NOTE]
> In CI we will be testing only last two releases and main branch on a regular basis.

| kube-prometheus stack                                                                      | Kubernetes 1.29 | Kubernetes 1.30 | Kubernetes 1.31 | Kubernetes 1.32 | Kubernetes 1.33 | Kubernetes 1.34 |
|--------------------------------------------------------------------------------------------|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
| [`release-0.14`](https://github.com/prometheus-operator/kube-prometheus/tree/release-0.14) | ✔               | ✔               | ✔               | x               | x               | x               |
| [`release-0.15`](https://github.com/prometheus-operator/kube-prometheus/tree/release-0.15) | x               | x               | ✔               | ✔               | ✔               | x               |
| [`release-0.16`](https://github.com/prometheus-operator/kube-prometheus/tree/release-0.16) | x               | x               | ✔               | ✔               | ✔               | ✔               |
| [`main`](https://github.com/prometheus-operator/kube-prometheus/tree/main)                 | x               | x               | x               | ✔               | ✔               | ✔               |


Question: How to: Quickstart

Answer:
This project is intended to be used as a library (i.e. the intent is not for you to create your own modified copy of this repository).

Though for a quickstart a compiled version of the Kubernetes [manifests](manifests) generated with this library (specifically with `example.jsonnet`) is checked into this repository in order to try the content out quickly. To try out the stack un-customized run:

* Create the monitoring stack using the config in the `manifests` directory:

  ```shell
  # Create the namespace and CRDs, and then wait for them to be available before creating the remaining resources
  # Note that due to some CRD size we are using kubectl server-side apply feature which is generally available since kubernetes 1.22.
  # If you are using previous kubernetes versions this feature may not be available and you would need to use kubectl create instead.
  kubectl apply --server-side -f manifests/setup
  kubectl wait \
      --for condition=Established \
      --all CustomResourceDefinition \
      --namespace=monitoring
  kubectl apply -f manifests/
  ```

We create the namespace and CustomResourceDefinitions first to avoid race conditions when deploying the monitoring components.
Alternatively, the resources in both folders can be applied with a single command
`kubectl apply --server-side -f manifests/setup -f manifests`, but it may be necessary to run the command multiple times for all components to
be created successfully.

* To teardown the stack:

  ```shell
  kubectl delete --ignore-not-found=true -f manifests/ -f manifests/setup
  ```

The [official documentation](http://prometheus-operator.dev/docs/getting-started/installation/) contains the full version of this quick-start guide, and includes [instructions](https://prometheus-operator.dev/kube-prometheus/kube/access-ui/) on how to access Prometheus, AlertManager, and Grafana.


Question: How to: Getting started

Answer:
Before deploying kube-prometheus in a production environment, read:

1. [Customizing kube-prometheus](docs/customizing.md)
2. [Customization examples](docs/customizations)
3. [Accessing Graphical User Interfaces](docs/access-ui.md)
4. [Troubleshooting kube-prometheus](docs/troubleshooting.md)


Question: How to: Documentation

Answer:
1. [Continuous Delivery](examples/continuous-delivery)
2. [Update to new version](docs/update.md)
3. For more documentation on the project refer to `docs/` directory.


Question: How to: Contributing

Answer: To contribute to kube-prometheus, refer to [Contributing](CONTRIBUTING.md).


Question: How to: Join the discussion

Answer: If you have any questions or feedback regarding kube-prometheus, join the [kube-prometheus discussion](https://github.com/prometheus-operator/kube-prometheus/discussions). Alternatively, consider joining [#prometheus-operator](https://kubernetes.slack.com/archives/CFFDS2Z7F) slack channel or project's bi-weekly [Contributor Office Hours](https://docs.google.com/document/d/1-fjJmzrwRpKmSPHtXN5u6VZnn39M28KqyQGBEJsqUOk/edit#).


Question: How to: Table of Contents

Answer:
- [Overview](#k8sgpt)
- [Installation](#cli-installation)
- [Quick Start](#quick-start)
- [Analyzers](#analyzers)
- [Examples](#examples)
- [LLM AI Backends](#llm-ai-backends)
- [Key Features](#key-features)
- [Model Context Protocol (MCP)](#model-context-protocol-mcp)
- [Documentation](#documentation)
- [Contributing](#contributing)
- [Community](#community)
- [License](#license)


Question: How to: Linux/Mac via brew

Answer:
```sh
brew install k8sgpt
```

or

```sh
brew tap k8sgpt-ai/k8sgpt
brew install k8sgpt
```
RPM-based installation (RedHat/CentOS/Fedora)
**32 bit:**
```
  sudo rpm -ivh https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.4.27/k8sgpt_386.rpm
  ```
**64 bit:**
```
  sudo rpm -ivh https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.4.27/k8sgpt_amd64.rpm
  ```
DEB-based installation (Ubuntu/Debian)
**32 bit:**
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.4.27/k8sgpt_386.deb
sudo dpkg -i k8sgpt_386.deb
```
**64 bit:**
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.4.27/k8sgpt_amd64.deb
sudo dpkg -i k8sgpt_amd64.deb
```
APK-based installation (Alpine)
**32 bit:**
```
  wget https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.4.27/k8sgpt_386.apk
  apk add --allow-untrusted k8sgpt_386.apk
  ```
**64 bit:**
```
  wget https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.4.27/k8sgpt_amd64.apk
  apk add --allow-untrusted k8sgpt_amd64.apk
  ```
Failing Installation on WSL or Linux (missing gcc)
When installing Homebrew on WSL or Linux, you may encounter the following error:

```
==> Installing k8sgpt from k8sgpt-ai/k8sgpt Error: The following formula cannot be installed from a bottle and must be
built from the source. k8sgpt Install Clang or run brew install gcc.
```

If you install gcc as suggested, the problem will persist. Therefore, you need to install the build-essential package.

```
   sudo apt-get update
   sudo apt-get install build-essential
```


Question: How to: Operator Installation

Answer:
To install within a Kubernetes cluster please use our `k8sgpt-operator` with installation instructions available [here](https://github.com/k8sgpt-ai/k8sgpt-operator)

_This mode of operation is ideal for continuous monitoring of your cluster and can integrate with your existing monitoring such as Prometheus and Alertmanager._


Question: How to: Quick Start

Answer:
- Currently, the default AI provider is OpenAI, you will need to generate an API key from [OpenAI](https://openai.com)
  - You can do this by running `k8sgpt generate` to open a browser link to generate it
- Run `k8sgpt auth add` to set it in k8sgpt.
  - You can provide the password directly using the `--password` flag.
- Run `k8sgpt filters` to manage the active filters used by the analyzer. By default, all filters are executed during analysis.
- Run `k8sgpt analyze` to run a scan.
- And use `k8sgpt analyze --explain` to get a more detailed explanation of the issues.
- You also run `k8sgpt analyze --with-doc` (with or without the explain flag) to get the official documentation from Kubernetes.


Question: How to: Using with Claude Desktop

Answer: K8sGPT can be integrated with Claude Desktop to provide AI-powered Kubernetes cluster analysis. This integration requires K8sGPT v0.4.14 or later.


Question: How to: Prerequisites

Answer:
1. Install K8sGPT v0.4.14 or later:
   ```sh
   brew install k8sgpt
   ```

2. Install Claude Desktop from the official website

3. Configure K8sGPT with your preferred AI backend:
   ```sh
   k8sgpt auth
   ```


Question: How to: Troubleshooting

Answer:
If you encounter connection issues:
1. Ensure K8sGPT is running with the MCP server enabled
2. Verify your Kubernetes cluster is accessible
3. Check that your AI backend is properly configured
4. Restart both K8sGPT and Claude Desktop

For more information, visit our [documentation](https://docs.k8sgpt.ai).


Question: How to: Built in analyzers

Answer:
#### Enabled by default

- [x] podAnalyzer
- [x] pvcAnalyzer
- [x] rsAnalyzer
- [x] serviceAnalyzer
- [x] eventAnalyzer
- [x] ingressAnalyzer
- [x] statefulSetAnalyzer
- [x] deploymentAnalyzer
- [x] jobAnalyzer
- [x] cronJobAnalyzer
- [x] nodeAnalyzer
- [x] mutatingWebhookAnalyzer
- [x] validatingWebhookAnalyzer
- [x] configMapAnalyzer

#### Optional

- [x] hpaAnalyzer
- [x] pdbAnalyzer
- [x] networkPolicyAnalyzer
- [x] gatewayClass
- [x] gateway
- [x] httproute
- [x] logAnalyzer
- [x] storageAnalyzer
- [x] securityAnalyzer
- [x] CatalogSource
- [x] ClusterCatalog
- [x] ClusterExtension
- [x] ClusterService
- [x] ClusterServiceVersion
- [x] OperatorGroup
- [x] InstallPlan
- [x] Subscription


Question: How to: Examples :

Answer:
- Simple filter : `k8sgpt filters add Service`
- Multiple filters : `k8sgpt filters add Ingress,Pod`

_Remove default filters_

```
k8sgpt filters remove [filter(s)]
```


Question: How to: Full serve mode with MCP

Answer:
k8sgpt serve --mcp --mcp-http --port 8080 --metrics-port 8081 --mcp-port 8089
```

The MCP server enables integration with tools like Claude Desktop and other MCP-compatible clients. It runs on port 8089 by default and provides:
- Kubernetes cluster analysis via MCP protocol
- Resource information and health status
- AI-powered issue explanations and recommendations

For Helm chart deployment with MCP support, see the `charts/k8sgpt/values-mcp-example.yaml` file.

_Analysis with serve mode_

```
grpcurl -plaintext -d '{"namespace": "k8sgpt", "explain" : "true"}' localhost:8080 schema.v1.ServerAnalyzerService/Analyze
{
  "status": "OK"
}
```

_Analysis with custom headers_

```
k8sgpt analyze --explain --custom-headers CustomHeaderKey:CustomHeaderValue
```

_Print analysis stats_

```
k8sgpt analyze -s
The stats mode allows for debugging and understanding the time taken by an analysis by displaying the statistics of each analyzer.
- Analyzer Ingress took 47.125583ms
- Analyzer PersistentVolumeClaim took 53.009167ms
- Analyzer CronJob took 57.517792ms
- Analyzer Deployment took 156.6205ms
- Analyzer Node took 160.109833ms
- Analyzer ReplicaSet took 245.938333ms
- Analyzer StatefulSet took 448.0455ms
- Analyzer Pod took 5.662594708s
- Analyzer Service took 38.583359166s
```

_Diagnostic information_

To collect diagnostic information use the following command to create a `dump_
_json` in your local directory.
```
k8sgpt dump
```


Question: How to: LLM AI Backends

Answer:
K8sGPT uses the chosen LLM, generative AI provider when you want to explain the analysis results using --explain flag e.g. `k8sgpt analyze --explain`. You can use `--backend` flag to specify a configured provider (it's `openai` by default).

You can list available providers using `k8sgpt auth list`:

```
Default:
> openai
Active:
Unused:
> openai
> localai
> ollama
> azureopenai
> cohere
> amazonbedrock
> amazonsagemaker
> google
> huggingface
> noopai
> googlevertexai
> watsonxai
> customrest
> ibmwatsonxai
```

For detailed documentation on how to configure and use each provider see [here](https://docs.k8sgpt.ai/reference/providers/backend/).

_To set a new default provider_

```
k8sgpt auth default -p azureopenai
Default provider set to azureopenai
```

_Using Amazon Bedrock with inference profiles_

_System Inference Profile_

```
k8sgpt auth add --backend amazonbedrock --providerRegion us-east-1 --model arn:aws:bedrock:us-east-1:123456789012:inference-profile/my-inference-profile

```

_Application Inference Profile_

```
k8sgpt auth add --backend amazonbedrock --providerRegion us-east-1 --model arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/2uzp4s0w39t6

```


Question: How to: Key Features

Answer:
With this option, the data is anonymized before being sent to the AI Backend. During the analysis execution, `k8sgpt` retrieves sensitive data (Kubernetes object names, labels, etc.). This data is masked when sent to the AI backend and replaced by a key that can be used to de-anonymize the data when the solution is returned to the user.
Anonymization
1. Error reported during analysis:

```bash
Error: HorizontalPodAutoscaler uses StatefulSet/fake-deployment as ScaleTargetRef which does not exist.
```

2. Payload sent to the AI backend:

```bash
Error: HorizontalPodAutoscaler uses StatefulSet/tGLcCRcHa1Ce5Rs as ScaleTargetRef which does not exist.
```

3. Payload returned by the AI:

```bash
The Kubernetes system is trying to scale a StatefulSet named tGLcCRcHa1Ce5Rs using the HorizontalPodAutoscaler, but it cannot find the StatefulSet. The solution is to verify that the StatefulSet name is spelled correctly and exists in the same namespace as the HorizontalPodAutoscaler.
```

4. Payload returned to the user:

```bash
The Kubernetes system is trying to scale a StatefulSet named fake-deployment using the HorizontalPodAutoscaler, but it cannot find the StatefulSet. The solution is to verify that the StatefulSet name is spelled correctly and exists in the same namespace as the HorizontalPodAutoscaler.
```


Question: How to: Further Details

Answer:
Note: **Anonymization does not currently apply to events.**

_In a few analysers like Pod, we feed to the AI backend the event messages which are not known beforehand thus we are not masking them for the **time being**._

- The following is the list of analysers in which data is **being masked**:-

  - Statefulset
  - Service
  - PodDisruptionBudget
  - Node
  - NetworkPolicy
  - Ingress
  - HPA
  - Deployment
  - Cronjob

- The following is the list of analysers in which data is **not being masked**:-

  - ReplicaSet
  - PersistentVolumeClaim
  - Pod
  - Log
  - **_\*Events_**

**\*Note**:

- k8gpt will not mask the above analysers because they do not send any identifying information except **Events** analyser.
- Masking for **Events** analyzer is scheduled in the near future as seen in this [issue](https://github.com/k8sgpt-ai/k8sgpt/issues/560). _Further research has to be made to understand the patterns and be able to mask the sensitive parts of an event like pod name, namespace etc._

- The following is the list of fields which are not **being masked**:-

  - Describe
  - ObjectStatus
  - Replicas
  - ContainerStatus
  - **_\*Event Message_**
  - ReplicaStatus
  - Count (Pod)

**\*Note**:

- It is quite possible the payload of the event message might have something like "super-secret-project-pod-X crashed" which we don't currently redact _(scheduled in the near future as seen in this [issue](https://github.com/k8sgpt-ai/k8sgpt/issues/560))_.


Question: How to: Proceed with care

Answer:
- The K8gpt team recommends using an entirely different backend **(a local model) in critical production environments**. By using a local model, you can rest assured that everything stays within your DMZ, and nothing is leaked.
- If there is any uncertainty about the possibility of sending data to a public LLM (open AI, Azure AI) and it poses a risk to business-critical operations, then, in such cases, the use of public LLM should be avoided based on personal assessment and the jurisdiction of risks involved.
Configuration management
`k8sgpt` stores config data in the `$XDG_CONFIG_HOME/k8sgpt/k8sgpt.yaml` file. The data is stored in plain text, including your OpenAI key.

Config file locations:
| OS | Path |
| ------- | ------------------------------------------------ |
| MacOS | ~/Library/Application Support/k8sgpt/k8sgpt.yaml |
| Linux | ~/.config/k8sgpt/k8sgpt.yaml |
| Windows | %LOCALAPPDATA%/k8sgpt/k8sgpt.yaml |
There may be scenarios where caching remotely is preferred.
In these scenarios K8sGPT supports AWS S3 or Azure Blob storage Integration.
Remote caching
Note: You can configure and use only one remote cache at a time
_Adding a remote cache_

- AWS S3
  - _As a prerequisite `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` are required as environmental variables._
  - Configuration, `k8sgpt cache add s3 --region
--bucket
`
  - Minio Configuration with HTTP endpoint ` k8sgpt cache add s3 --bucket
--endpoint
`
  - Minio Configuration with HTTPs endpoint, skipping TLS verification ` k8sgpt cache add s3 --bucket
--endpoint
--insecure`
    - K8sGPT will create the bucket if it does not exist
- Azure Storage
  - We support a number of [techniques](https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication?tabs=bash#2-authenticate-with-azure) to authenticate against Azure
  - Configuration, `k8sgpt cache add azure --storageacc
--container
`
    - K8sGPT assumes that the storage account already exist and it will create the container if it does not exist
    - It is the **user** responsibility have to grant specific permissions to their identity in order to be able to upload blob files and create SA containers (e.g Storage Blob Data Contributor)
- Google Cloud Storage
  - _As a prerequisite `GOOGLE_APPLICATION_CREDENTIALS` are required as environmental variables._
  - Configuration, ` k8sgpt cache add gcs --region
--bucket
--projectid
`
    - K8sGPT will create the bucket if it does not exist

_Listing cache items_

```
k8sgpt cache list
```

_Purging an object from the cache_
Note: purging an object using this command will delete upstream files, so it requires appropriate permissions.

```
k8sgpt cache purge $OBJECT_NAME
```

_Removing the remote cache_
Note: this will not delete the upstream S3 bucket or Azure storage container

```
k8sgpt cache remove
```
Custom Analyzers
There may be scenarios where you wish to write your own analyzer in a language of your choice.
K8sGPT now supports the ability to do so by abiding by the [schema](https://github.com/k8sgpt-ai/schemas/blob/main/protobuf/schema/v1/custom_analyzer.proto) and serving the analyzer for consumption.
To do so, define the analyzer within the K8sGPT configuration and it will add it into the scanning process.
In addition to this you will need to enable the following flag on analysis:

```
k8sgpt analyze --custom-analysis
```

Here is an example local host analyzer in [Rust](https://github.com/k8sgpt-ai/host-analyzer)
When this is run on `localhost:8080` the K8sGPT config can pick it up with the following additions:

```
custom_analyzers:
  - name: host-analyzer
    connection:
      url: localhost
      port: 8080
```

This now gives the ability to pass through hostOS information ( from this analyzer example ) to K8sGPT to use as context with normal analysis.

_See the docs on how to write a custom analyzer_

_Listing custom analyzers configured_
```
k8sgpt custom-analyzer list
```

_Adding custom analyzer without install_
```
k8sgpt custom-analyzer add --name my-custom-analyzer --port 8085
```

_Removing custom analyzer_
```
k8sgpt custom-analyzer remove --names "my-custom-analyzer,my-custom-analyzer-2"
```


Question: How to: Model Context Protocol (MCP)

Answer:
K8sGPT provides a Model Context Protocol server that exposes Kubernetes operations as standardized tools for AI assistants like Claude, ChatGPT, and other MCP-compatible clients.

**Start the MCP server:**

Stdio mode (for local AI assistants):
```bash
k8sgpt serve --mcp
```

HTTP mode (for network access):
```bash
k8sgpt serve --mcp --mcp-http --mcp-port 8089
```

**Features:**
- 12 tools for cluster analysis, resource management, and debugging
- 3 resources for cluster information access
- 3 interactive troubleshooting prompts
- Stateless HTTP mode for one-off invocations
- Full integration with Claude Desktop and other MCP clients

**Learn more:** See [MCP.md](MCP.md) for complete documentation, usage examples, and integration guides.


Question: How to: Documentation

Answer: Find our official documentation available [here](https://docs.k8sgpt.ai)


Question: How to: Admin Interface

Answer:
* [ActiveAdmin](http://activeadmin.info) - A Ruby on Rails framework for creating elegant backends for website administration.
* [ActiveScaffold](https://github.com/activescaffold/active_scaffold) - ActiveScaffold provides quick and powerful user interfaces for CRUD (create, read, update, delete) operations for Rails applications. It's excellent for generating admin interfaces, managing Data-Heavy Applications, creating Widgets or for quick prototyping. ActiveScaffold is completly customizable and offers a bunch of additional features including searching, pagination, layout control and overrides of fields, forms and templates.
* [Administrate](https://github.com/thoughtbot/administrate) - A Rails engine that helps you put together a super-flexible admin dashboard, by Thoughtbot.
* [Avo Admin for Rails](https://avohq.io/rails-admin) - Avo is the modern approach to building an advanced admin panel that can be used by the entire organization. It has all the tools an admin panel needs and more. We have carefully made sure that you have all the escape hatches you need to ensure you can build your next admin panel for Ruby on Rails incredibly fast and easily.
* [bhf](http://antpaw.github.io/bhf/) - A simple to use Rails-Engine-Gem that offers an admin interface for trusted user.
* [Hot Glue](https://github.com/hot-glue-for-rails/hot-glue/) - Hot Glue takes a different approach to building both admin and user dashboards. It is a code generation tool like the Rails scaffold generator but with significantly more features. Instead of providing a lot of configuration options, Hot Glue can generate your code. Good for lists & CRUD views for both admin and user-facing dashboards.
* [Madmin](https://github.com/excid3/madmin) - A robust Admin Interface for Ruby on Rails apps
* [MotorAdmin](https://github.com/motor-admin/motor-admin-rails) - A low-code Admin panel and Business Intelligence Rails engine. No DSL - configurable from the UI.
* [RailsAdmin](https://github.com/sferik/rails_admin) - A Rails engine that provides an easy-to-use interface for managing your data.
* [Trestle](https://github.com/TrestleAdmin/trestle) - A modern, responsive admin framework for Rails. Build a back-end in minutes that will grow with the needs of your application.


Question: How to: API Builder and Discovery

Answer:
* [ActiveModel::Serializers](https://github.com/rails-api/active_model_serializers) - JSON serialization of objects.
* [Acts_As_Api](https://github.com/fabrik42/acts_as_api) - Easy And Fun, in creating XML/JSON responses in Rails 3,4,5 and 6.
* [Alba](https://github.com/okuramasafumi/alba) - A JSON serializer for Ruby, JRuby and TruffleRuby.
* [Blanket](https://github.com/inf0rmer/blanket) - A dead simple API wrapper.
* [Blueprinter](https://github.com/procore/blueprinter) - Simple, Fast, and Declarative Serialization Library for Ruby.
* [cache_crispies](https://github.com/codenoble/cache-crispies) - Speedy Rails JSON serialization with built-in caching.
* [Crepe](https://github.com/crepe/crepe) - The thin API stack.
* [EasyTalk](https://github.com/sergiobayona/easy_talk) - Define structured data models with a DSL that generates JSON Schema and ActiveModel validations from a single source of truth.
* [Grape](http://www.ruby-grape.org) - An opinionated micro-framework for creating REST-like APIs in Ruby.
* [Her](https://github.com/remiprev/her) - an ORM that maps REST resources to Ruby objects. Designed to build applications that are powered by a RESTful API instead of a database.
* [jbuilder](https://github.com/rails/jbuilder) - Create JSON structures via a Builder-style DSL.
* [jsonapi-rb](http://jsonapi-rb.org) – Efficient and convenient JSON API (de)serialization library.
* [jsonapi-serializer](https://github.com/jsonapi-serializer/jsonapi-serializer) - A fast JSON:API serializer for Ruby Objects.
* [JSONAPI::Resources](https://github.com/cerebris/jsonapi-resources) - JSONAPI::Resources, or "JR", provides a framework for developing a server that complies with the JSON API specification.
* [JSONAPI::Utils](https://github.com/tiagopog/jsonapi-utils) - JSONAPI::Utils is built on top of JSONAPI::Resources taking advantage of its resource-driven style and bringing an easy way to build modern JSON APIs with no or less learning curve.
* [Jsonite](https://github.com/crepe/jsonite) - A tiny, HAL-compliant JSON presenter for your APIs.
* [Pliny](https://github.com/interagent/pliny) - Opinionated template Sinatra app for writing excellent APIs in Ruby.
* [rabl](https://github.com/nesquena/rabl) - General ruby templating with json, bson, xml, plist and msgpack support.
* [Roar](https://github.com/apotonick/roar) - Resource-Oriented Architectures in Ruby.
* [Spyke](https://github.com/balvig/spyke) - Interact with REST services in an ActiveRecord-like manner.
* [Version Cake](https://github.com/bwillis/versioncake) - An unobtrusive way to version APIs in your Rails app.
* [versionist](https://github.com/bploetz/versionist) - A plugin for versioning Rails based RESTful APIs.


Question: How to: Authentication and OAuth

Answer:
* [API Guard](https://github.com/Gokul595/api_guard) - JWT authentication solution for Rails APIs.
* [Authentication Zero](https://github.com/lazaronixon/authentication-zero) - An authentication system generator for Rails applications.
* [Authlogic](https://github.com/binarylogic/authlogic) - Authlogic is a clean, simple, and unobtrusive ruby authentication solution.
* [Clearance](https://github.com/thoughtbot/clearance) - Small and simple email & password based authentication for Rails.
* [Devise](https://github.com/heartcombo/devise) - A flexible authentication solution for Rails based on Warden.
* [JWT](https://github.com/jwt/ruby-jwt) - JSON Web Token implementation in Ruby.
* [Monban](https://github.com/halogenandtoast/monban) - A very simple and extensible user authentication library for rails.
* [OmniAuth](https://github.com/omniauth/omniauth) - A library that standardizes multi-provider authentication utilizing Rack middleware.
* [Rodauth](https://github.com/jeremyevans/rodauth) - Authentication and account management framework for Rack applications.
* [Sorcery](https://github.com/Sorcery/sorcery) - A stripped-down, bare-bones authentication library for Rails.
* [warden](https://github.com/hassox/warden) - General Rack Authentication Framework.
* OAuth:
  * [Doorkeeper](https://github.com/doorkeeper-gem/doorkeeper) - An OAuth2 provider for Rails.
  * [OAuth2](https://github.com/intridea/oauth2) - A Ruby wrapper for the OAuth 2.0 protocol.
  * [Rodauth-Oauth](https://gitlab.com/honeyryderchuck/rodauth-oauth) - A rodauth OAuth and OpenID provider plugin.


Question: How to: Authorization

Answer:
* [acl9](https://github.com/be9/acl9) - Acl9 is a role-based authorization system that provides a concise DSL for securing your Rails application.
* [AccessGranted](https://github.com/chaps-io/access-granted) - Multi-role and whitelist based authorization gem for Rails.
* [ActionPolicy](https://github.com/palkan/action_policy) - Authorization framework for Ruby and Rails applications. Composable, extensible and performant.
* [CanCanCan](https://github.com/CanCanCommunity/cancancan) - Continuation of CanCan, an authorization Gem for Ruby on Rails.
* [Consul](https://github.com/makandra/consul) - A scope-based authorization solution for Ruby on Rails.
* [Petergate](https://github.com/elorest/petergate) - Easy to use and read action and content based authorizations.
* [Pundit](https://github.com/elabs/pundit) - Minimal authorization through OO design and pure Ruby classes.
* [Rabarber](https://github.com/brownboxdev/rabarber) - Simple role-based authorization for Rails with multi-tenancy support.


Question: How to: Automation

Answer:
* [ActiveWorkflow](https://github.com/automaticmode/active_workflow) - An intelligent process and workflow automation platform based on software agents.
* [Danger](https://github.com/danger/danger) - Automate your team's conventions surrounding code review.
* [Huginn](https://github.com/cantino/huginn) - Huginn is a system for building agents that perform automated tasks for you online.
* [Neovim](https://github.com/alexgenco/neovim-ruby) - Ruby bindings for Neovim to make your own neovim editor plugins in Ruby.
* [Runbook](https://github.com/braintree/runbook) - A framework and Ruby DSL for progressive system automation.


Question: How to: Breadcrumbs

Answer:
* [Breadcrumbs on Rails](https://github.com/weppos/breadcrumbs_on_rails) - A simple Ruby on Rails plugin for creating and managing a breadcrumb navigation for a Rails project.
* [Gretel](https://github.com/lassebunk/gretel) - A Ruby on Rails plugin that makes it easy yet flexible to create breadcrumbs.
* [loaf](https://github.com/peter-murach/loaf) - Manages and displays breadcrumb trails in Rails app - lean & mean.
* [Simple Navigation](https://github.com/codeplant/simple-navigation) - A ruby gem for creating navigation (html list, link list or breadcrumbs with multiple levels) for your Rails 2, 3 & 4, Sinatra or Padrino.


Question: How to: Boilerplates & UI Kits

Answer:
* [Jumpstart](https://jumpstartrails.com/) - The Ruby on Rails SaaS template to save you months of development time.
* [Rails Blocks](https://railsblocks.com) - Delightful UI components for your Rails app that use Tailwind CSS & Stimulus controllers.
* [Speedrail](https://github.com/ryanckulp/speedrail) - A free Rails 8 app template: Devise auth, Stripe billing, Tailwind CSS, admin panel, SEO helpers, etc.
* [Wheel](https://github.com/bigbinary/wheel) - Rails application template to build Rails applications faster.


Question: How to: Captchas and anti-spam

Answer:
* [ActsAsTextcaptcha](https://github.com/matthutchinson/acts_as_textcaptcha) - Protection for Rails models with text-based logic question captchas (from Rob Tuley's textcaptcha.com)
* [Invisible Captcha](https://github.com/markets/invisible_captcha) - Unobtrusive and flexible spam protection based on the honeypot strategy. It also provides a time-sensitive form submission.
* [Rakismet](https://github.com/joshfrench/rakismet) - Easy Akismet and TypePad AntiSpam integration for Rails.
* [reCAPTCHA](https://github.com/ambethia/recaptcha) - reCaptcha API helpers for ruby apps.
* [Voight-Kampff](https://github.com/biola/Voight-Kampff) - A Ruby gem that detects bots, spiders, crawlers and replicants.


Question: How to: CLI Builder

Answer:
* [Clamp](https://github.com/mdub/clamp) - A command-line application framework.
* [cmdparse](http://cmdparse.gettalong.org) - An advanced command line parser supporting nested commands.
* [Commander](https://github.com/commander-rb/commander) - The complete solution for Ruby command-line executables.
* [dry-cli](https://github.com/dry-rb/dry-cli) - General purpose Command Line Interface (CLI) framework for Ruby.
* [GLI](https://github.com/davetron5000/gli) - Git-Like Interface Command Line Parser.
* [Main](https://github.com/ahoward/main) - A class factory and DSL for generating command line programs real quick.
* [Optimist](https://github.com/ManageIQ/optimist) - A commandline option parser for Ruby that just gets out of your way.
* [Rake](https://github.com/ruby/rake) - A make-like build utility for Ruby.
* [Runfile](https://github.com/DannyBen/runfile) - Build command line applications per project with ease. Rake-inspired, Docopt inside.
* [Slop](https://github.com/leejarvis/slop) - Simple Lightweight Option Parsing.
* [Terrapin](https://github.com/thoughtbot/terrapin) - A small command line library (Formerly Cocaine).
* [Thor](http://whatisthor.com) - A toolkit for building powerful command-line interfaces.
* [TTY](https://github.com/peter-murach/tty) - Toolbox for developing CLI clients.


Question: How to: CLI Utilities

Answer:
* [Awesome Print](https://github.com/awesome-print/awesome_print) - Pretty print your Ruby objects with style -- in full color and with proper indentation
* [Betty](https://github.com/pickhardt/betty) - Friendly English-like interface for your command line. Don't remember a command? Ask Betty.
* [colorize](https://github.com/fazibear/colorize) - Extends String class or add a ColorizedString with methods to set text color, background color and text effects.
* [colorls](https://github.com/athityakumar/colorls) - Beautifies the `ls` command, with color and font-awesome icons.
* [formatador](https://github.com/geemus/formatador) - STDOUT text formatting.
* [Paint](https://github.com/janlelis/paint) - Simple and fast way to set ANSI terminal colors.
* [Pastel](https://github.com/peter-murach/pastel) - Terminal output styling with intuitive and clean API.
* [Ru](https://github.com/tombenner/ru) - Ruby in your shell.
* [Ruby/Progressbar](https://github.com/jfelchner/ruby-progressbar) - The most flexible text progress bar library for Ruby.
* [Tabulo](https://github.com/matt-harvey/tabulo) - Plain text table generator with a DRY, column-based API.
* [TablePrint](https://github.com/arches/table_print) - Slice your data from multiple DB tables into a single CLI view.
* [Terminal Table](https://github.com/tj/terminal-table) - Ruby ASCII Table Generator, simple and feature rich.
* [Tmuxinator](https://github.com/tmuxinator/tmuxinator) - Create and manage complex tmux sessions easily.
* [Whirly](https://github.com/janlelis/whirly) - A simple, colorful and customizable terminal spinner library for Ruby.


Question: How to: Code Analysis and Metrics

Answer:
* [Brakeman](https://github.com/presidentbeef/brakeman) - A static analysis security vulnerability scanner for Ruby on Rails applications.
* [Coverband](https://github.com/danmayer/coverband) - Rack middleware to help measure production code coverage.
* [Fasterer](https://github.com/DamirSvrtan/fasterer) - Make your Rubies go faster with this command line tool highly inspired by fast-ruby and Sferik's talk at Baruco Conf.
* [Flay](https://github.com/seattlerb/flay) - Flay analyzes code for structural similarities. Differences in literal values, variable, class, method names, whitespace, programming style, braces vs do/end, etc are all ignored. Making this totally rad.
* [Flog](https://github.com/seattlerb/flog) - Flog reports the most tortured code in an easy to read pain report. The higher the score, the more pain the code is in.
* [fukuzatsu](https://gitlab.com/coraline/fukuzatsu#fukuzatsu) - Complexity analysis tool with a rich web front-end.
* [MetricFu](https://github.com/metricfu/metric_fu) - A fist full of code metrics.
* [Pippi](https://github.com/tcopeland/pippi) - A utility for finding suboptimal Ruby class API usage, focused on runtime analysis.
* [Pronto](https://github.com/mmozuras/pronto) - Quick automated code review of your changes.
* [rails_best_practices](https://github.com/railsbp/rails_best_practices) - A code metric tool for rails projects.
* [Reek](https://github.com/troessner/reek) - Code smell detector for Ruby.
* [Rubycritic](https://github.com/whitesmith/rubycritic) - A Ruby code quality reporter.
* [Scientist](https://github.com/github/scientist) - A Ruby library for carefully refactoring critical paths.
* [SimpleCov](https://github.com/colszowka/simplecov) - Code coverage for Ruby 1.9+ with a powerful configuration library and automatic merging of coverage across test suites.
* [Sorbet](https://github.com/sorbet/sorbet) - A static type checker for Ruby.
* [Suture](https://github.com/testdouble/suture) - A Ruby gem that helps you refactor your legacy code.
* [Traceroute](https://github.com/amatsuda/traceroute) - A Rake task gem that helps you find the dead routes and actions for your Rails 3+ app


Question: How to: Code Formatting

Answer:
* [niceql](https://github.com/alekseyl/niceql) - A dependentless SQL and SQL errors formatting and colorizing. ActiveRecord seemless integration.
* [prettier](https://github.com/prettier/plugin-ruby) - A prettier plugin for the Ruby language.
* [RuboCop](https://github.com/rubocop-hq/rubocop) - A static code analyzer, based on the community Ruby style guide.
  * [Rubocop Rails](https://github.com/rubocop-hq/rubocop-rails) - A RuboCop extension focused on enforcing Rails best practices and coding conventions.
  * [Rubocop Rspec](https://github.com/rubocop-hq/rubocop-rspec) - Code style checking for RSpec files
  * [Rubocop Performance](https://github.com/rubocop-hq/rubocop-performance) - A RuboCop extension focused on code performance checks.
* [Standard](https://github.com/testdouble/standard) - Ruby Style Guide, with linter & automatic code fixer


Question: How to: Code Highlighting

Answer:
* [CodeRay](https://github.com/rubychan/coderay) - Fast and easy syntax highlighting for selected languages.
* [pygments.rb](https://github.com/tmm1/pygments.rb) - A Ruby wrapper for the Python pygments syntax highlighter.
* [Rouge](https://github.com/jneen/rouge) - A pure Ruby code highlighter that is compatible with Pygments.


Question: How to: Code Loaders

Answer: * [Zeitwerk](https://github.com/fxn/zeitwerk) - An efficient and thread-safe Ruby code loader.


Question: How to: Coding Style Guides

Answer:
* [Best-Ruby](https://github.com/franzejr/best-ruby) - Ruby Tricks, Idiomatic Ruby, Refactoring & Best Practices.
* [fast-ruby](https://github.com/JuanitoFatas/fast-ruby) - Writing Fast Ruby. Collect Common Ruby idioms.
* [Fundamental Ruby](https://github.com/khusnetdinov/ruby.fundamental) - Fundamental programming ruby with examples. Threads, design patterns, data structures, OOP SOLID principle, algorithms.
* [Rails style guide](https://github.com/bbatsov/rails-style-guide) - Community-driven Rails best practices and style for Rails 3 and 4.
* [RSpec style guide](https://github.com/andreareginato/betterspecs) - Better Specs { rspec guidelines with ruby }.
* [Ruby Operators](http://ruby-operators.herokuapp.com/) - A webpage showing awesome names for different Ruby operators.
* [Ruby style guide](https://github.com/bbatsov/ruby-style-guide) - Community-driven Ruby coding style.


Question: How to: Concurrency and Parallelism

Answer:
* [Concurrent Ruby](https://github.com/ruby-concurrency/concurrent-ruby) - Modern concurrency tools including agents, futures, promises, thread pools, supervisors, and more. Inspired by Erlang, Clojure, Scala, Go, Java, JavaScript, and classic concurrency patterns.
* [EventMachine](https://github.com/eventmachine/eventmachine) - An event-driven I/O and lightweight concurrency library for Ruby.
* [forkoff](https://github.com/ahoward/forkoff) - brain-dead simple parallel processing for ruby.
* [Parallel](https://github.com/grosser/parallel) - Run any code in parallel Processes (> use all CPUs) or Threads (> speedup blocking operations). Best suited for map-reduce or e.g. parallel downloads/uploads.
* [Polyphony](https://github.com/digital-fabric/polyphony) - Fine-grained concurrency for Ruby.


Question: How to: Configuration

Answer:
* [AnywayConfig](https://github.com/palkan/anyway_config) - Configuration library for Ruby gems and applications, supporting multiple sources (yml, secrets) and environments.
* [Chamber](https://github.com/thekompanee/chamber) - Surprisingly customizable convention-based approach to managing your app's configuration.
* [Configatron](https://github.com/markbates/configatron) - Simple and feature rich configuration system for Ruby apps.
* [Configus](https://github.com/kaize/configus) - Helps you easily manage environment specific settings.
* [dotenv](https://github.com/bkeepers/dotenv) - Loads environment variables from `.env`.
* [Econfig](https://github.com/elabs/econfig) - Flexible configuration for Rails applications.
* [ENVied](https://github.com/eval/envied) - ensure presence and type of your app's ENV-variables
* [Envyable](https://github.com/philnash/envyable) - The simplest YAML to ENV config loader.
* [Figaro](https://github.com/laserlemon/figaro) - Simple, Heroku-friendly Rails app configuration using `ENV` and a single YAML file.
* [Global](https://github.com/railsware/global) - Provides accessor methods for your configuration data.
* [RailsConfig](https://github.com/railsconfig/config) - Multi-environment yaml settings for Rails3.
* [Sail](https://github.com/vinistock/sail) - A lightweight Rails engine that brings an admin panel for managing configuration settings on a live Rails app.


Question: How to: Core Extensions

Answer:
* [ActiveSupport](https://github.com/rails/rails/tree/master/activesupport) - A collection of utility classes and standard library extensions.
* [Addressable](https://github.com/sporkmonger/addressable) - Addressable is a replacement for the URI implementation that is part of Ruby's standard library. It more closely conforms to RFC 3986, RFC 3987, and RFC 6570 (level 4), providing support for IRIs and URI templates.
* [Bitwise](https://github.com/kenn/bitwise) - Fast, memory efficient bitwise operations on large binary strings
* [Finishing Moves](https://github.com/forgecrafted/finishing_moves) - Small, focused, incredibly useful methods added to core Ruby classes. Includes the endlessly useful `nil_chain`.
* [Docile](https://github.com/ms-ati/docile) - A tiny library that lets you map a DSL (domain specific language) to your Ruby objects in a snap.
* [dry-rb](https://github.com/dry-rb) - dry-rb is a collection of next-generation Ruby libraries, each intended to encapsulate a common task.
* [Hamster](https://github.com/hamstergem/hamster) - Efficient, immutable, and thread-safe collection classes for Ruby.
* [Hanami::Utils](https://github.com/hanami/utils) - Lightweight, non-monkey-patch class utilities for Hanami and Ruby app.
* [MemoWise](https://github.com/panorama-ed/memo_wise) - Memoize any instance/class/module method, including support for frozen objects - rigorously tested and benchmarked on all Rubies - fast performance of memoized reads.
* [Ruby Facets](https://github.com/rubyworks/facets) - The premiere collection of general purpose method extensions and standard additions for Ruby.
* [Trick Bag](https://github.com/keithrbennett/trick_bag) - Assorted Ruby classes and methods to simplify and enhance your code.
* Attributes
  * [ActiveAttr](https://github.com/cgriego/active_attr) - What ActiveModel left out.
  * [Virtus](https://github.com/solnic/virtus) - Attributes on Steroids for Plain Old Ruby Objects.
  * [AttrExtras](https://github.com/barsoom/attr_extras) - Takes some boilerplate out of Ruby with methods like attr_initialize.
* Hash
  * [Hashie](https://github.com/intridea/hashie) - A collection of tools that extend Hashes and make them more useful.
* String
  * [string_pattern](https://github.com/MarioRuiz/string_pattern) - Generate strings supplying a simple pattern.


Question: How to: Country Data

Answer:
* [Carmen](https://github.com/jim/carmen) - A repository of geographic regions.
* [Countries](https://github.com/hexorx/countries) - All sorts of useful information about every country packaged as pretty little country objects.
* [i18n_data](https://github.com/grosser/i18n_data) - country/language names and 2-letter-code pairs, in 85 languages, for country/language i18n.
* [normalize_country](https://github.com/sshaw/normalize_country) - Convert country names and codes to a standard, includes a conversion program for XMLs, CSVs and DBs.
* [Phonelib](https://github.com/daddyz/phonelib) - Ruby gem for phone validation and formatting using Google libphonenumber library data.
* [Phony](https://github.com/floere/phony) - Fast international phone number (E164 standard) normalizing, splitting and formatting.
* [validates_zipcode](https://github.com/dgilperez/validates_zipcode) - Postal code / zipcode validation for Rails, supporting 233 country codes.


Question: How to: Cryptocurrencies and Blockchains

Answer:
* [Blockchain Lite](https://github.com/openblockchains/blockchain.lite.rb) - Build your own blockchains with crypto hashes; revolutionize the world with blockchains, blockchains, blockchains one block at a time.
* [Ciri](https://github.com/ciri-ethereum/ciri) - Ruby implementation of Ethereum.
* [MoneyTree](https://github.com/GemHQ/money-tree) - A Ruby implementation of Bitcoin HD Wallets (Hierarchical Deterministic) BIP32.
* [Peatio](https://github.com/rubykube/peatio) - Most Advanced Cryptocurrency open-source assets exchange.


Question: How to: Dashboards

Answer:
* [Blazer](https://github.com/ankane/blazer) - Simple data viewer using only SQL. Output to table, chart, and maps.
* [Smashing](https://smashing.github.io/) - Smashing is a Sinatra based framework that lets you build beautiful dashboards. This project is the maintained spiritual successor to the Dashing framework.
* [Dashing-Rails](https://github.com/gottfrois/dashing-rails) - The exceptionally handsome dashboard framework for Rails.


Question: How to: Data Processing and ETL

Answer:
* [attr-gather](https://github.com/ianks/attr-gather) - A gem for creating workflows that "enhance" entities with extra attributes. At a high level, attr-gather provides a process to fetch information from many data sources (such as third party APIs, legacy databases, etc.) in a fully parallelized fashion.
* [CSV Reader](https://github.com/csvreader/csvreader) - A modern tabular data (line-by-line records) reader supports "classic" CSV but also CSV Numerics, `CSV <3 JSON`, `CSV <3 YAML`, tab, space or fixed width fields (FWF) and many more flavors and dialects.
* [json-streamer](https://github.com/thisismydesign/json-streamer) - Stream JSON data based on various criteria (key, nesting level, etc).
* [Kiba](http://www.kiba-etl.org) - A lightweight data processing / ETL framework for Ruby.
* [Multiwoven](https://github.com/Multiwoven/multiwoven) - The open-source reverse ETL, data activation platform developed using Ruby and Ruby on Rails.
* [ruby-stemmer](https://github.com/aurelian/ruby-stemmer) - It Provides Snowball algorithm for stemming purposes.


Question: How to: Data Visualization

Answer:
* [Chartkick](http://chartkick.com/) - Create beautiful Javascript charts with one line of Ruby.
* [GeoPattern](https://github.com/jasonlong/geo_pattern) - Create beautiful generative geometric background images from a string.
* [LazyHighCharts](https://github.com/michelson/lazy_high_charts) - A simple and extremely flexible way to use HighCharts from ruby code. Tested on Ruby on Rails, Sinatra and Nanoc, but it should work with others too.
* [ApexCharts.rb](https://github.com/styd/apexcharts.rb) - Awesome charts for your ruby app. Works on any ruby app, including Rails app. It even works on plain HTML+ERB files.
* [RailRoady](https://github.com/preston/railroady) - Ruby on Rails 3/4 model and controller UML class diagram generator.
* [Rails Erd](https://github.com/voormedia/rails-erd) - Generate Entity-Relationship Diagrams for Rails applications.
* [Ruby/GraphViz](https://github.com/glejeune/Ruby-Graphviz) - Ruby interface to the GraphViz graphing tool.