Quick start

Take a small TypeScript service from no Redline to a merge gate that has earned its rung. Ten short steps. Each one is a commit and a pull request in a real repository you can open, so you can read along or build it yourself.

✓

redlinegate@0.2.10 is the version on npm's latest tag, published 2026-10-12. Every command on this page installs it.

✓

You will learn

  • How to onboard a repository with one command
  • How to read a finding, ask why the rule exists, and fix it properly
  • How to add your team's own rules
  • What the merge gate checks, and which failures nothing can waive
  • How to merge past a check on the record, with an exemption
  • How a repository earns blocking enforcement

What you are building

redline-demo is a tiny user and address service. Every step below is one pull request there, merged into main and tagged step-NN, so git log --first-parent main reads like this page:

StepWhat you will see
00 · The starting pointa small TypeScript service with tests and CI, before Redline
01 · Onboardone command adds the rules, the review commands and a merge gate
02 · Your first findingfour broken rules, caught on your machine and in the pipeline
03 · Explain and fixwhy a rule exists, and fixing the code instead of silencing it
04 · A team ruleyour team's own rule, in every assistant and in the review
05 · A big change needs an ADRpast 300 lines, write the decision down
06 · The security floora vulnerable dependency fails the gate at every rung
07 · Make the gate requireda red gate disables the merge button
08 · Exemptionsmerge past a failing check, on the record
09 · Earn a stricter rungblocking is earned with evidence, never switched on

Setup

You need Node 18.11 or later, pnpm, git and the GitHub CLI, signed in with gh auth login. You do not install Redline: every command runs it with npx.

Option 1: read along

Clone the finished repository and check out any step to see exactly what it held.

terminal
$ git clone https://github.com/moelzanaty3/redline-demo.git
$ cd redline-demo
$ git checkout step-00
$ pnpm install
$ pnpm test

Option 2: build it yourself

Start your own copy from step 00, on your own GitHub account, and run every command below against it. The demo stays connected as a remote called demo, so a step can borrow its larger files.

terminal
$ git clone https://github.com/moelzanaty3/redline-demo.git
$ cd redline-demo
$ git remote rename origin demo
$ git checkout -B main step-00
$ gh repo create redline-demo --public --source . --remote origin --push
$ pnpm install
$ pnpm test

ℹ pass 2
ℹ fail 0
ℹ

Make it public. Dependency review and secret scanning, which step 06 relies on, are free on public repositories and need GitHub Advanced Security on private ones. Merge each step's pull request before you start the next one, and branch from an up-to-date main.

Step 00 · The starting point

A TypeScript service with strict compiler settings, two tests, and a CI workflow that runs them. Nothing here knows about Redline. Every later step changes this repository and nothing else.

See it in the demo: git checkout step-00

Step 01 · Onboard

One command, from the repository root:

terminal
$ npx redlinegate@latest init --gate-source local

  profile javascript-typescript
  Files  21 written
   + AGENTS.md
   + CLAUDE.md
   + .github/copilot-instructions.md
   + .github/workflows/redline.yml
   + .github/workflows/redline-gate.yml
   + .redline.json
   …
  Repository settings  6 in place · 1 unavailable
   ✓ applied     secret-scanning    secret scanning
   ✓ applied     dependency-alerts  dependabot alerts (vulnerability alerts)
   ✓ applied     merge-policy       branch ruleset
  Pull request
   https://github.com/<you>/redline-demo/pull/1

It did three things:

  • Rules for your assistants. AGENTS.md, CLAUDE.md, the Copilot instructions and the Cursor rules, read on every request.
  • A merge gate. .github/workflows/redline.yml runs on every pull request. --gate-source local keeps the gate inside this repository; a real team would reference one from its organisation's .github repository instead, which a pull request cannot edit.
  • Repository settings. Secret scanning, push protection, Dependabot alerts, and a branch ruleset on main that requires a pull request and no approving review. Redline fails the pipeline; whether a person must also approve is your choice (--approvals <n>).

It committed all of it on a branch and opened the pull request itself. Merge it.

See it in the demo: git checkout step-01 · pull request #1

Step 02 · Your first finding

Write the kind of code an assistant produces when told to make a type error go away. It compiles, and the tests still pass:

terminal
$ git checkout -b feat/load-user
src/user.ts
type User = { id: string; name: string }

// TODO: handle retries
export function loadUser(raw: string) {
  // @ts-ignore
  return JSON.parse(raw) as unknown as User
}

export type Payload = unknown

Ask Redline before you push:

terminal
$ git add src/user.ts
$ npx redlinegate@latest review

profile javascript-typescript — rules in scope: core, typescript
src/user.ts:3
  Redline/HIGH [core/untracked-todo]: this TODO carries no ticket reference, so nothing will bring anyone back to it.
src/user.ts:5
  Redline/BLOCKER [core/type-checker-suppression]: a type-checker suppression needs an inline explanation AND a ticket reference on the same line.
src/user.ts:6
  Redline/BLOCKER [core/unsafe-assertion]: a double assertion overrides the type checker with no stated reason.
src/user.ts:9
  Redline/HIGH [typescript/unknown-type-alias]: this alias names `unknown`, so it reads as a contract it is not.
4 finding(s)

Every finding names a severity (BLOCKER must not merge, HIGH is a deliberate trade-off), a rule id in brackets, and the problem. No model was called: these four rules are decided by a checker.

Push it and open a pull request anyway, to see the pipeline:

terminal
$ git commit -m "feat: load a user from JSON"
$ git push -u origin feat/load-user
$ gh pr create --fill

Deterministic policy fails with the same four findings, and the gate still passes. Every repository starts at the observe rung: Redline reports first, so a team sees what it would block before anything is blocked.

See it in the demo: git checkout step-02 · pull request #2

Step 03 · Explain and fix

Take any rule id from a finding and ask what it means:

terminal
$ npx redlinegate@latest explain core/unsafe-assertion

BLOCKER core/unsafe-assertion

  No unsafe assertions (`as unknown as X`, force casts) used to silence an error. …

  decided by   a checker, with no model call
  defined in   standards/core.md:87

Then fix the code rather than the symptom: check the parsed JSON with a type predicate, and there is nothing left to assert or suppress.

src/user.ts
export type User = { id: string; name: string }

function isUser(value: unknown): value is User {
  return (
    typeof value === 'object' &&
    value !== null &&
    'id' in value &&
    typeof value.id === 'string' &&
    'name' in value &&
    typeof value.name === 'string'
  )
}

export function loadUser(raw: string): User {
  const parsed: unknown = JSON.parse(raw)
  if (!isUser(parsed)) throw new Error('payload is not a User')
  return parsed
}
terminal
$ git add src/user.ts
$ npx redlinegate@latest review

profile javascript-typescript — rules in scope: core, typescript
no findings

Push it; every check on the pull request goes green.

See it in the demo: git checkout step-03 · pull request #3

Step 04 · A team rule

The org standard covers what every repository shares. Your team's own rules go in one file:

.redline/local.md
## Errors are returned, not logged

This service is a library: the code that calls it decides what to log and where.

- `local/no-console` — No `console.*` calls in `src/`. Throw an `Error` with a message that says what was wrong, and let the caller log it.
terminal
$ npx redlinegate@latest init --no-commit

Redline renders the rule into every assistant file, under a # Repository-local rules heading, and into the prompt /redline-review uses. A team rule is prose, so a model applies it: add a console.log to src/ and run /redline-review in Claude Code, Copilot or Cursor to see [local/no-console].

See it in the demo: git checkout step-04 · pull request #4

Step 05 · A big change needs an ADR

Large changes usually carry a decision. Past 300 changed lines, the gate asks for an Architecture Decision Record linked from the pull request. Borrow the demo's address parser and its 249-country table:

terminal
$ git checkout -b feat/addresses
$ git checkout step-05 -- src/countries.ts src/countries.test.ts src/address.ts src/address.test.ts
$ pnpm test
$ git commit -m "feat: parse addresses, with the country checked against ISO 3166"
$ git push -u origin feat/addresses
$ gh pr create --fill

changed=352 threshold=300 adr-links=0 no-adr-label=0
Error: 352 changed lines with no ADR link.

Write the decision down (context, options, choice, consequences) in docs/adr/0001-country-list-in-code.md, commit it, and add a link to it under ## Architecture decision in the pull request description. Editing the description re-runs the gate. A large change that makes no decision, such as a generated lockfile, takes the no-adr label instead.

See it in the demo: git checkout step-05 · pull request #5

Step 06 · The security floor

So far every failure was soft: reported, not blocking. Dependency review and the secret scan are different. They fail the gate at every rung, and no label waives them.

terminal
$ git checkout -b feat/directory
$ pnpm add lodash@4.17.20 --save-exact
$ pnpm add -D @types/lodash
$ git checkout step-06 -- src/directory.ts src/directory.test.ts
$ git add -A && git commit -m "feat: group countries by initial"
$ git push -u origin feat/directory
$ gh pr create --fill

package.json » lodash@4.17.20 – Command Injection in lodash (high severity)
Error: Redline gate failed on security checks (not label-exemptible,
       and not on the enforcement ladder): dependency-review

Try gh pr edit --add-label redline-exempt: the gate notices the label and fails anyway. The fix is the upgrade:

terminal
$ pnpm add lodash@4.18.1 --save-exact
$ git commit -am "fix(deps): lodash 4.18.1"
$ git push

See it in the demo: git checkout step-06 · pull request #6

Step 07 · Make the gate required

A red gate has been advice so far: GitHub still let you merge. Make it a required check:

terminal
$ git checkout main && git pull
$ npx redlinegate@latest init --blocking

   ✓ applied     merge-policy       branch ruleset
  Pull request
   https://github.com/<you>/redline-demo/pull/<n>

The ruleset on main now requires redline-gate / gate, for everyone, admins included. Push the vulnerable lodash pin to that pull request and gh pr view --json mergeStateStatus says BLOCKED; revert it and it says CLEAN. At observe only the security floor turns the gate red, so this changes nothing for a broken rule yet.

See it in the demo: git checkout step-07 · pull request #12

Step 08 · Exemptions

Sometimes a check is right and you merge anyway, on purpose. Rename loadUser to parseUser with no alias: that breaks anyone importing it, so the checklist item Rollback is safe stays honestly unticked and PR checklist fails.

A redline-exempt label alone records nothing, and the gate says so. Add this to the pull request description as well:

pull request description
## Redline exemption

- reason: parseUser replaces loadUser with no alias, so a consumer that upgrades cannot roll back without renaming its import again. Nothing outside this repository imports it yet.
- until: YYYY-MM-DD
- scope: checklist

Check it on your machine first, against the check that is failing:

terminal
$ gh pr view --json body --jq .body > body.md
$ npx redlinegate@latest exempt --body-file body.md --scope checklist

exempt until YYYY-MM-DD (checklist): parseUser replaces loadUser with no alias, …

Set until to a real date. The reason needs 20 characters or more, the expiry must be within 90 days, and the scope names the checks it covers. An exemption never covers the security floor. At observe it changes the record, not the merge; once a repository blocks, it is the only way past a failing process check.

See it in the demo: git checkout step-08 · pull request #14

Step 09 · Earn a stricter rung

Blocking on findings is not a setting you flip. The ladder runs observe → block-blocker → block-high, and each rung asks for a measurement:

terminal
$ npx redlinegate@latest evidence
$ npx redlinegate@latest evidence record --sample-size 7 --acted-on-rate 1 \
$   --source "PRs #2-#6, #12, #14: the gate ran on each; all 4 findings on #2 were fixed in #3"
$ npx redlinegate@latest init --rung block-blocker --no-commit

  ▲ enforcement stays at observe — cannot move to block-blocker:
  ▲ 20 reviewed pull requests are needed and 7 have been recorded
  ▲ the seeded corpus has never been scored for this stack, so there is no
    evidence the reviewer catches known defects at all
  ▲ the clean corpus has never been scored, so nothing shows the reviewer stays
    quiet on correct code

That refusal is the point. Before Redline may stop a merge on its findings, it must catch every known defect in a seeded corpus, flag nothing in a clean one, and show 20 pull requests of people agreeing with what it found. The evidence is recorded in .redline.json with its source, and is reviewed like any other change. Stepping down never needs evidence: --rung observe always works.

See it in the demo: git checkout step-09 · pull request #15

Wrapping up

You took one repository through everything Redline does:

  • The same rules reach your assistant, your terminal and the pull request.
  • Findings name a rule you can look up, and a fix that removes the problem rather than the warning.
  • The security floor blocks from day one, and nothing waives it.
  • Everything else reports first, and blocks only once the evidence says it is right.
  • Merging past a check is allowed, and written down: who, why, until when.

Next steps