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

# Running fyrer in CI with Caching and Plain Log Output

> Run fyrer in CI with plain output mode and prefixed logs, leverage content-addressed caching to skip unchanged tasks, and fail fast on errors.

fyrer works in CI environments with the `-n` / `--no-tui` flag, which disables the interactive TUI and prints plain, prefixed log output to stdout. Combined with caching, fyrer can skip unchanged tasks across CI runs — so only the packages that actually changed get rebuilt.

## Disable the TUI

Pass `-n` (or `--no-tui`) to get CI-friendly output:

```bash theme={null}
fyrer run build -n
```

Each line of output is prefixed with the originating package and task:

```text theme={null}
[ui:build]  $ bun build src/index.ts --outdir dist
[ui:build]  Built 42 modules in 310ms
[api:build] $ cargo build --release
[api:build]    Compiling api v0.1.0
```

Lines are colorized per package, making it easy to trace output even when multiple tasks run concurrently.

## Exit codes

fyrer uses standard POSIX exit codes so your CI pipeline can react automatically:

* **Exit `0`** — all tasks succeeded (including tasks that were cached or skipped).
* **Exit non-zero** — one or more tasks failed.

Tasks whose dependencies failed are automatically skipped (not retried), and their skipped status does not itself cause a non-zero exit — only actual failures do. Use this behavior to fail your pipeline precisely on task failure:

```bash theme={null}
fyrer run build -n || exit 1
```

## Caching in CI

fyrer stores its content-addressed cache under `.fyrer/cache/` relative to `fyrer.yml`. Each cached task is keyed by a **blake3** hash of the task definition, environment, and the contents of every file matched by `inputs`. If the key matches a previous run, the task is reported as `⚡ Cached` and skipped — its `outputs` are restored from the archive.

To benefit from caching across CI runs, persist the `.fyrer/cache` directory between jobs. Here is a GitHub Actions cache step:

```yaml .github/workflows/ci.yml theme={null}
- name: Cache fyrer build outputs
  uses: actions/cache@v3
  with:
    path: .fyrer/cache
    key: fyrer-${{ hashFiles('**/fyrer.yml') }}-${{ hashFiles('**/src/**') }}
    restore-keys: |
      fyrer-${{ hashFiles('**/fyrer.yml') }}-
```

## Full CI workflow example

A complete GitHub Actions workflow that installs fyrer, restores the cache, and builds the monorepo:

```yaml .github/workflows/ci.yml theme={null}
name: CI
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Cache fyrer outputs
        uses: actions/cache@v3
        with:
          path: .fyrer/cache
          key: fyrer-${{ hashFiles('fyrer.yml') }}-${{ github.sha }}
          restore-keys: fyrer-${{ hashFiles('fyrer.yml') }}-
      - name: Install fyrer
        run: curl -fsSL https://raw.githubusercontent.com/07calc/fyrer/main/install.sh | sh
      - name: Build
        run: fyrer run build -n
```

<Tip>
  Use `fyrer plan build` before `fyrer run build -n` to print the topological execution plan without running any commands. This is helpful for debugging dependency ordering issues in CI without wasting build time.
</Tip>

<Note>
  Do **not** run persistent tasks (dev servers) in CI. A task with `persistent: true` never exits, so your CI job will block indefinitely. Only include tasks that have a finite lifecycle — i.e. tasks without `persistent: true`.
</Note>
