CI Setup

Run Nark on every pull request, block merges on new violations, and upload the audit JSON as a workflow artifact.

What you get

Once wired in, Nark runs on every pull request against your default branch. Each run prints a step summary with total violations, a per-package breakdown, and a link to the audit JSON. New violations introduced by the PR fail the check. Existing violations are baselined and do not block the merge. The full audit JSON is uploaded as a workflow artifact with a 30-day retention window.

Prerequisites

  • A TypeScript project with a resolvable tsconfig.json. Nark reads it to build the type checker.
  • Node 18 or later on your CI runner.
  • GitHub Actions, or comparable CI that can run a composite action (GitLab, CircleCI, Buildkite all work with minor adaptation of the YAML below).

Free-tier setup

This uses only the public Nark profile library (169+ profiles covering axios, prisma, stripe, openai, and the other common packages). No token required.

Drop this into .github/workflows/nark.yml:

# .github/workflows/nark.yml
name: Nark
on: [pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci

      - uses: nark-sh/nark-action@v3
        with:
          diff-base: ${{ github.event.pull_request.base.sha }}

The three steps:

  1. Check out the repo with fetch-depth: 0 so the diff base is available.
  2. Install your dependencies. Nark needs node_modules on disk to resolve types.
  3. Run nark-sh/nark-action@v3. The diff-base input scopes findings to the lines the PR actually touched.

Design-partner setup (with @nark-sh/corpus-pro)

If you have been granted access to the private profile library, you get the public 169+ profiles plus the long-tail SDK coverage (@aws-sdk/*, @azure/*, @google-cloud/*, niche infra packages, and faster version-fork iteration).

Two additions on top of the free-tier workflow.

1. Create a Personal Access Token

In GitHub go to Settings, Developer settings, Personal access tokens, Tokens (classic). Generate a new token with only the read:packages scope. Copy the token.

In your target repo go to Settings, Secrets and variables, Actions, and add a repository secret named NARK_CORPUS_PRO_TOKEN with the token value.

Your account also needs a package-side access grant. Confirm with Caleb, or check github.com/orgs/nark-sh/packages/npm/corpus-pro/settings.

2. Pass the token to the action

Update your workflow to include the corpus-token input:

# .github/workflows/nark.yml
name: Nark
on: [pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci

      - uses: nark-sh/nark-action@v3
        with:
          corpus-token: ${{ secrets.NARK_CORPUS_PRO_TOKEN }}
          diff-base: ${{ github.event.pull_request.base.sha }}

The action writes an .npmrc block, installs @nark-sh/corpus-pro ephemerally, and passes it to Nark alongside the public corpus. If you prefer to manage .npmrc yourself, the equivalent lines are:

@nark-sh:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NARK_CORPUS_PRO_TOKEN}

What the PR check does

The Nark step summary shows total violations, the count of newly-added violations since the PR base, and each violation with file:line plus a fix hint. The check fails when any new violation appears. Existing violations are baselined and pass through silently so you can adopt Nark incrementally without a red build on day one.

Telemetry

When the Nark CLI runs interactively it sends anonymous scan metadata (installed package names and versions, per-package violation counts, scan duration, Node version, OS, architecture) to app.nark.sh/api/telemetry/scan. No source code, no file paths, no repo names, no user data. The GitHub Action disables telemetry by default in CI (set telemetry: true on the action to opt in). To disable interactive telemetry too, set NARK_TELEMETRY=off in the environment or run nark telemetry off. Full details on the telemetry page.

Troubleshooting

Job passes but no violations file is uploaded

The scanner crashed before writing output. Check the Run nark step log. Most common cause is OOM (exit 134) on mid-sized TypeScript programs. The action defaults node-options to --max-old-space-size=8192 already; if you still OOM, raise it further or split your tsconfig.

Exit 134 (OOM) on the Run nark step

Pass node-options: '--max-old-space-size=12288' to nark-action, or use a larger runner (e.g. ubuntu-latest-4-cores). Very large monorepos may also benefit from scanning per-package tsconfigs in a matrix.

Cannot find module '@nark-sh/corpus-pro' after adding corpus-token

Your PAT is missing the read:packages scope, or your account has not been granted access to the package at github.com/orgs/nark-sh/packages/npm/corpus-pro. Regenerate the token with read:packages and confirm access with Caleb.

No tsconfig.json found

Pass tsconfig: path/to/tsconfig.json to nark-action explicitly. The scanner needs a real TypeScript project file to resolve types; without it every import comes back as any and the scan is worthless.

Scanner ran but reports 0 violations on a repo you know has some

Check that npm ci ran before the nark step and that node_modules exists. Nark uses the TypeScript type checker; without installed dependencies every package call resolves as any and no profile matches.

What's next

Once Nark is green on your PRs, wire it into your AI review loop. Pipe the audit JSON into Claude Code, Cursor, or your agent of choice so the scanner findings shape the fix, not just gate the merge. See the AI-native workflow guide for the recommended pattern. Bugs, missing profiles, or feature requests go on github.com/nark-sh/nark.