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:
| Step | What you will see |
|---|---|
| 00 · The starting point | a small TypeScript service with tests and CI, before Redline |
| 01 · Onboard | one command adds the rules, the review commands and a merge gate |
| 02 · Your first finding | four broken rules, caught on your machine and in the pipeline |
| 03 · Explain and fix | why a rule exists, and fixing the code instead of silencing it |
| 04 · A team rule | your team's own rule, in every assistant and in the review |
| 05 · A big change needs an ADR | past 300 lines, write the decision down |
| 06 · The security floor | a vulnerable dependency fails the gate at every rung |
| 07 · Make the gate required | a red gate disables the merge button |
| 08 · Exemptions | merge past a failing check, on the record |
| 09 · Earn a stricter rung | blocking 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.
$ 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.
$ 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:
$ 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.ymlruns on every pull request.--gate-source localkeeps the gate inside this repository; a real team would reference one from its organisation's.githubrepository instead, which a pull request cannot edit. - Repository settings. Secret scanning, push protection, Dependabot alerts, and a branch ruleset on
mainthat 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:
$ git checkout -b feat/load-user
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:
$ 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:
$ 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:
$ 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.
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
}
$ 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:
## 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.
$ 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:
$ 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.
$ 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:
$ 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:
$ 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:
## 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:
$ 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:
$ 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
- Onboard a repository: your own, with the options this walkthrough skipped.
- Tutorial: the same first finding on a throwaway repository on your machine, with no GitHub needed.
- Enforcement ladder and Exemptions: the rules behind steps 08 and 09.
- Troubleshooting: every failure that actually happens, and the command that resolves it.