> For the complete documentation index, see [llms.txt](https://docs.scanner.dev/scanner/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.scanner.dev/scanner/using-scanner-complete-feature-reference/detections-and-alerting/detection-rules/detection-rules-as-code/getting-started.md).

# Getting Started

### 1. Put your detection rules in a Git repository

We recommend [creating a new GitHub repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-new-repository) in your organization for Scanner detection rules. However, any Git host works for the user-pushed flow below — GitHub is only required if you want Scanner to poll the repository for you.

Add detection rule YAML files to your repository. See [Writing Detection Rules](/scanner/using-scanner-complete-feature-reference/detections-and-alerting/detection-rules/detection-rules-as-code/writing-detection-rules.md) for information on how to write detection rules.

### 2. Choose a sync mode

Scanner supports two ways to bring rules from a repository into your tenant. Both run the same validate / test / materialize pipeline, so the synced rules look the same either way — pick whichever matches how your team manages rules.

* **GitHub-polled** — Scanner pulls from a GitHub.com repository connected through the Scanner GitHub App, every \~5 minutes. Use this when your rules live in GitHub.com and the App can be granted read access. Continue with [GitHub-polled sync](#set-up-github-polled-sync) below.
* **User-pushed** — your CI (or you, locally) pushes the repository to Scanner, typically via the [Scanner GitHub Action](https://github.com/scanner-inc/sync-detection-rules) or directly via [`scanner-cli`](/scanner/using-scanner-complete-feature-reference/detections-and-alerting/detection-rules/detection-rules-as-code/cli.md). Use this when your rules live outside GitHub.com — for example on GitLab, Bitbucket, or a self-hosted GitHub Enterprise Server — when the Scanner GitHub App can't be granted access, or when sync should run from CI. Skip ahead to [user-pushed sync](#set-up-user-pushed-sync).

## Set up GitHub-polled sync

### Connect to the Scanner GitHub App

Go to **Settings > Integrations** on your Scanner instance to connect your GitHub account.

<figure><img src="/files/YlcqGBhgi6AKcjfx4B8g" alt="" width="563"><figcaption><p>Integrations page</p></figcaption></figure>

Choose which account to connect to and which repositories the Scanner GitHub App can access. The App will **only** have read access to code and metadata in the selected repositories.

You will need to be logged into GitHub and have appropriate permissions on the selected repositories in order to complete this process.

<figure><img src="/files/hZW9WkqNFzalXwSDW1OK" alt="" width="563"><figcaption><p>Allow access to select repositories</p></figcaption></figure>

If you want to connect multiple accounts, click on **Connect** again to select another account.

You will be able to configure repositories after connecting to the GitHub App, if you want to give the Scanner App access to more repositories or revoke access to repositories later.

### Add a polled sync source

After connecting your GitHub account, go to **Detection Rule: GitHub Settings**.

<figure><img src="/files/WuEt7FXmDqMF4brDY6GF" alt="" width="563"><figcaption><p>GitHub integration options</p></figcaption></figure>

On this page, you will see all connected GitHub accounts and sync sources.

<figure><img src="/files/wVVxV0nHBNrBxWrEXhrq" alt="" width="563"><figcaption><p>GitHub settings page</p></figcaption></figure>

To add a new sync source, click **Add Repository**. Select the repository and branch that you would like to sync from.

<figure><img src="/files/K9Qt1YQ1fekmdJaxBEte" alt="" width="563"><figcaption><p>Add a sync source</p></figcaption></figure>

You will be prompted to assign event sinks to each key in this sync source. You can select one or more event sinks to assign to each key (or leave it blank). These keys are defined in the detection rules themselves; see the [Writing Detection Rules](/scanner/using-scanner-complete-feature-reference/detections-and-alerting/detection-rules/detection-rules-as-code/writing-detection-rules.md#detection-rule-event-sinks) section for more information.

<figure><img src="/files/PViQVLyCbR7eYVPZKeVp" alt="" width="563"><figcaption><p>Assign event sinks</p></figcaption></figure>

A sync will automatically kick off after you add a sync source. Syncs happen every 5 minutes (if there have been new commits since the last attempted sync). They can be kicked off manually on the **Detections** page or via [API](/scanner/using-scanner-complete-feature-reference/developer-tools/api/git-sync.md).

<figure><img src="/files/OztuC2QU1QwpyaLyNy2I" alt="" width="371"><figcaption><p>Kick off a GitHub sync</p></figcaption></figure>

## Set up user-pushed sync

### Add a push sync source

Go to **Detections > Synced Repositories** on your Scanner instance and add a new push sync source. You'll be asked to choose two things:

* A **push key** — a per-tenant identifier you'll use to target this source on every push. Pick something short and stable (e.g. the repo's slug).
* A **branch** that the source tracks (typically your default branch). The source must be registered for the same branch you'll push from — for example, a GitHub Action triggered on `push: branches: [main]` needs a source registered for `main`, and a `scanner-cli sync-git-repo` run from a `main` checkout works the same way. To sync from more than one branch, register a separate push sync source per branch.

<figure><img src="/files/mYdVnFr3S8DG2FxZtMZT" alt="" width="563"><figcaption><p>Add a push sync source</p></figcaption></figure>

Detection rules can reference event-sink keys (see [Writing Detection Rules](/scanner/using-scanner-complete-feature-reference/detections-and-alerting/detection-rules/detection-rules-as-code/writing-detection-rules.md#detection-rule-event-sinks)). Unlike the GitHub-polled flow, the event-sink assignment step in the UI only becomes available **after your first push** — Scanner discovers which keys exist by reading the uploaded rules. You'll come back to this step after running the sync the first time.

### Push from your rules repository

You have two options for invoking the sync. Both end up running the same `scanner-cli sync-git-repo` upload under the hood — the server validates, tests, and materializes the rules in exactly the same way.

{% tabs %}
{% tab title="GitHub Action (recommended for GitHub.com / GHES)" %}
Use the [`scanner-inc/sync-detection-rules`](https://github.com/scanner-inc/sync-detection-rules) Action. It installs `scanner-cli`, runs the sync against the checked-out tree, and surfaces per-file failures and warnings as PR / check annotations on the offending YAML files.

```yaml
name: Sync Detection Rules
on:
  push:
    branches: [main]

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: scanner-inc/sync-detection-rules@v0.1.0
        with:
          scanner_api_url: ${{ vars.SCANNER_API_URL }}
          scanner_api_key: ${{ secrets.SCANNER_API_KEY }}
          push_key: ${{ vars.SCANNER_PUSH_KEY }}
```

`scanner_api_key` is the only sensitive value — store it as a [repository secret](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions). `scanner_api_url` (from **Settings > API Keys** in Scanner) and `push_key` (the identifier you picked on the push sync source) aren't credentials — uploads are authorized by the API key — so configure them as [repository variables](https://docs.github.com/en/actions/learn-github-actions/variables) instead. Variables are visible in workflow logs, which makes debugging easier.
{% endtab %}

{% tab title="Run scanner-cli directly" %}
Use this when the GitHub Action isn't an option — e.g. rules hosted on GitLab, Bitbucket, or another non-GitHub host, in CI systems other than GitHub Actions, or for ad-hoc local runs.

Install [`scanner-cli`](/scanner/using-scanner-complete-feature-reference/detections-and-alerting/detection-rules/detection-rules-as-code/cli.md#installation) and configure [authentication](/scanner/using-scanner-complete-feature-reference/detections-and-alerting/detection-rules/detection-rules-as-code/cli.md#authentication). Then, from a checkout of your rules repository, run:

```bash
scanner-cli sync-git-repo --push-key <push-key>
```

This uploads the tracked files in the working tree (via `git ls-files`) to Scanner. See [CLI](/scanner/using-scanner-complete-feature-reference/detections-and-alerting/detection-rules/detection-rules-as-code/cli.md) for the full command reference, including `validate` and `run-tests`.
{% endtab %}
{% endtabs %}

### Assign event sinks (after the first push)

Scanner can only discover the event-sink keys your rules reference by reading rules that have actually been uploaded, so event-sink assignment happens **after** your first successful push — regardless of which option above you used.

If you set up the GitHub Action, trigger it at least once (push a commit to the configured branch, or run the workflow manually from the Actions tab) so Scanner has rules to discover keys from.

Then, in **Detections > Synced Repositories**, open the sync source you created. Scanner now lists the event-sink keys your rules reference — assign one or more event sinks to each key. See [Writing Detection Rules](/scanner/using-scanner-complete-feature-reference/detections-and-alerting/detection-rules/detection-rules-as-code/writing-detection-rules.md#detection-rule-event-sinks) for how the keys are declared in rule YAML.

Until you do, rules referencing unassigned keys will sync, but won't deliver alerts to any sink.

## Check the status of your sync

The sync source detail page shows the same information regardless of mode — the last sync attempt, the detection rules that were included, and any failures or warnings. Open it from **Detections > Synced Repositories** (or by clicking on the connected repository, for GitHub-polled sync).

<figure><img src="/files/5F3sq8hsuoi2Wl6qTWjo" alt="" width="563"><figcaption><p>Last sync status and included rules</p></figcaption></figure>

If there are no errors or failing tests, the detection rules will be synced and you will see them on the **Detections** page with a tag identifying the sync source.

<figure><img src="/files/Yzha8eD9qSwp0JPR27h0" alt=""><figcaption><p>Synced detection rule</p></figcaption></figure>

If any rule fails to validate or its tests fail, the sync does not proceed and the failure list shows which files were rejected and why. After fixing the files:

* **GitHub-polled** — check in the changes; the next scheduled sync will pick them up, or kick off a sync manually from the **Detections** page.
* **User-pushed** — trigger the GitHub Action again (or re-run `scanner-cli sync-git-repo`).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.scanner.dev/scanner/using-scanner-complete-feature-reference/detections-and-alerting/detection-rules/detection-rules-as-code/getting-started.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
