[](LICENSE) [](https://www.npmjs.com/package/@gnt-ai/cli) [](https://github.com/gnt-ai/gnt/releases/latest) [](https://www.repo-grade.com/report/gnt-ai/gnt)
Run the setup below once and every agent your team runs has a **git-native rulebook** it has to check over **MCP** before it acts, approved the same way your code already is: a **merged pull request**.
- Rules live in your repo as files and ship through normal PRs, not a dashboard click.
- Agents call `check_action` over MCP before anything risky (a refund, a delete, a message to a customer) and get back an allow/block/escalate verdict.
- Every rule traces back to the git file and the PR that approved it, so "why did the agent do that" always has a paper trail.
> Prefer not to run any of this yourself? The hosted version at [gntai.dev](https://gntai.dev) does the same thing without you standing up a Postgres instance.
## Get started (30 seconds)
```bash
npm install -g @gnt-ai/cli
gnt login
gnt connect github
gnt prebrain
# merge the opened PR on GitHub. that merge is the approval
```
### Try it with Docker first
To see a real `check_action` response before installing Node or npm, clone
the repository and run the Docker-only demo:
```bash
./demo.sh
```
It builds the full local stack in an isolated `gnt-demo` Compose project,
seeds an approved refund rule, calls `check_action`, and prints a curl command
you can run again. Without an Anthropic key the real fail-closed path returns
`needs_human`; pass `GNT_DEMO_ANTHROPIC_API_KEY=sk-ant-... ./demo.sh` to opt in
to the model's grounded policy verdict. The demo uses deterministic local embeddings and
throwaway localhost-only secrets, so it does not need a ZeroEntropy key.

> Nothing for `gnt prebrain` to scan yet? Run `gnt init` first — it scaffolds `rules/` locally
> with a couple of example rule files so there's something real to look at and edit, and points
> you at `gnt prebrain --starter-packs` for a curated pack to start from instead.
That merge lands a rule file in your connected repo, shaped like this:
```
your-repo/
└── rules/
├── refund-approval-threshold.md
└── contract-legal-cc.md
```
Each file is plain markdown with YAML frontmatter:
```markdown
---
title: Never refund over $500 without a manager
status: approved
confidence: 0.91
owner_id: finance-team
source_citations: [...]
source: slack
tags: [refunds, finance]
last_validated_at: 2026-07-20
version: 1
superseded_by: null
approved_by: jane@company.com
approved_at: 2026-07-21T14:03:00Z
created_at: 2026-07-18T09:12:00Z
pr_number: 142
pr_url: https://github.com/your-org/your-repo/pull/142
---
Refunds over $500 need manager sign-off before they go out...
```
## See it in action
There's no captured transcript to show yet (see the gap noted at the bottom of this README).
Here's the actual response shape a `check_action` call returns, straight from the tool's
contract:
```json
{
"verdict": "blocked",
"reason": "Refund exceeds the $500 threshold without manager sign-off (rules/refund-approval-threshold.md)",
"cited_rules": [
{ "id": "refund-approval-threshold", "title": "Never refund over $500 without a manager" }
],
"rules_retrieved": 3
}
```
`verdict` is one of `allowed`, `blocked`, or `needs_human`. `needs_human` is the fail-closed
default: no approved rule covers the action, retrieval failed, or the check couldn't complete.
It never guesses.
## What it does
One MCP endpoint, five tools:
| Tool | What it does |
| --- | --- |
| `check_action` | Checks a described action against your approved rules before an agent takes it. Returns `allowed`, `blocked`, or `needs_human` with cited rules and a one-line reason. |
| `search_rules` | Semantic search over your org's approved rules, optionally filtered by tag. An empty list means no approved rule covers the query. |
| `get_rule` | Fetches one approved rule by id, with its provenance (who approved it, when, what it was cited from). |
| `list_skill_packs` | Lists every compiled skill pack version for your org, newest first. |
| `get_skill_pack` | Fetches a compiled skill pack's manifest and file list by id. |
## Prerequisites
| Requirement | Check | Get it |
| --- | --- | --- |
| Node >=22.13 | `node --version` | [nodejs.org](https://nodejs.org) |
## Install
| Method | Command |
| --- | --- |
| curl | `curl -fsSL gntai.dev/install.sh \| sh` |
| npm | `npm install -g @gnt-ai/cli` |
> gnt needs Node >=22.13. If the CLI fails to start with a version error, update Node first and confirm with `node --version`.
## Common commands
```bash
gnt login # sign in, store an API key locally
gnt init # scaffold a local rules/ dir with example rule files
gnt connect github # connect the repo your rules PRs open against
gnt prebrain # scan sources, extract candidate rules, open PRs
gnt review # review rules awaiting approval
gnt status # show brain status
gnt pull # download the latest skill pack
gnt gaps # list uncovered queries with no approved rule
```
## Config
| Variable | Default | What it controls |
| --- | --- | --- |
| `GNT_API_URL` | `https://api.gntai.dev` | API endpoint the CLI and MCP calls hit |
| `GNT_WEB_URL` | `https://gntai.dev` | Web app used for `gnt login`'s browser step |
| `GNT_CONFIG_DIR` | `~/.gnt` | Where `credentials.json` and local config live |
## Privacy
- No analytics or telemetry dependency in the CLI or the web app.
- `gnt prebrain`'s default extraction mode is cloud, not on-device: your source text goes straight to Anthropic's API (or Vercel AI Gateway with zero-data-retention, if you configure it), never to gnt's own servers. Fully on-device extraction needs `--mode local` against a local Ollama daemon.
- The extracted rule candidates still get sent to gnt's API to open the PR. Raw source text stays off gnt's servers in cloud mode; the resulting rule text doesn't.
- Rules live in your connected GitHub repo and in gnt's own database. The MCP tools read from gnt's store, not by cloning your repo on every call.
- Self-hosting: `apps/api` only sends error data to Sentry if you set `SENTRY_DSN` yourself. Leave it unset and nothing goes out.
## Team setup
- **Who writes rules**: anyone with access to your connected repo, either through `gnt prebrain` (batch-extracted from real sources) or `gnt review` (hand-proposed).
- **How approval works**: merging the PR is the approval. There's no separate publish step.
- **What gets committed**: `rules/