Skip to main content
Glama
HITMANdark07

neatcode-mcp

by HITMANdark07
README.md
<div align="center">

```text
                          _                     _
   _ __    ___    __ _   | |_    ___   ___   __| |   ___
  | '_ \  / _ \  / _` |  | __|  / __| / _ \ / _` |  / _ \
  | | | ||  __/ | (_| |  | |_  | (__ | (_) | (_| | |  __/
  |_| |_| \___|  \__,_|   \__|  \___| \___/ \__,_|  \___|
```

# ๐Ÿง  neatcode

**Local-first repo intelligence for AI coding agents.**
*The graph your agent wishes it had.*

[![npm version](https://img.shields.io/npm/v/@neatcodeai/cli?color=cb3837&logo=npm&label=%40neatcodeai%2Fcli)](https://www.npmjs.com/package/@neatcodeai/cli)
[![npm downloads](https://img.shields.io/npm/dm/@neatcodeai/cli?color=blue&logo=npm)](https://www.npmjs.com/package/@neatcodeai/cli)
[![license](https://img.shields.io/npm/l/@neatcodeai/cli?color=green)](./LICENSE)
[![node](https://img.shields.io/node/v/@neatcodeai/cli?color=339933&logo=nodedotjs)](https://nodejs.org)
[![types](https://img.shields.io/badge/types-strict-3178c6?logo=typescript)](#typescript-compatibility)
[![mcp](https://img.shields.io/badge/MCP-ready-7c3aed)](#mcp-integration)

</div>

---

> Stop letting your agent re-grep your repo on every turn.
> neatcode indexes your TypeScript codebase into a real AST graph, learns the conventions your code already follows, and answers your agent's structural questions over MCP โ€” **deterministic, no LLM in the hot path**.

```text
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        MCP         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚  ๐Ÿ’ป your editor  โ”‚  โ—€โ”€โ”€โ”€โ”€stdioโ”€โ”€โ”€โ”€โ”€โ–ถ  โ”‚  โš™๏ธ  neatcode-mcp  (11 tools)    โ”‚
   โ”‚                  โ”‚                    โ”‚                                 |
   โ”‚  Claude Code     โ”‚                    โ”‚  ๐Ÿ” query_graph     ๐Ÿ“ find_node โ”‚
   โ”‚  Cursor          โ”‚                    โ”‚  ๐Ÿ›ค๏ธ  trace_flow      โœ… validate โ”‚
   โ”‚  Codex           โ”‚                    โ”‚  ๐Ÿ’ก propose_rule    ๐Ÿ“š get_rules โ”‚
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                    โ”‚  ๐Ÿ“ add_note    ๐Ÿ“‹ repo_overview โ”‚
                                           โ”‚  โฎ• accept_proposed_rule         โ”‚
                                           โ”‚  โฎ• derive_candidates            โ”‚
                                           โ”‚  โฎ• accept_derived_candidates    โ”‚
                                           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                            โ”‚
                                                โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                                โ”‚   ๐Ÿ“‚ .neatcode/       โ”‚
                                                โ”‚    โ”œโ”€โ”€ graph.db       โ”‚
                                                โ”‚    โ”œโ”€โ”€ skills.yaml    โ”‚
                                                โ”‚    โ”œโ”€โ”€ decisions.yaml โ”‚
                                                โ”‚    โ””โ”€โ”€ REPO_OVERVIEW  โ”‚
                                                โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
```

## ๐Ÿ’ก Why

| Without neatcode | With neatcode |
| --- | --- |
| Agent re-greps the repo every turn | Agent calls `query_graph` against an indexed AST |
| "What conventions does this repo follow?" โ†’ vibes | Heuristic miner derives conventions from real code |
| Agent writes `BookingHandler` despite a Controller convention | `validate_diff` flags it before the file is written |
| Rules live in tribal memory or stale `CONTRIBUTING.md` | Rules live in `.neatcode/skills.yaml`, validated bidirectionally |
| Each chat starts cold | `get_repo_overview` ships the one-page brief at session start |

---

## ๐Ÿš€ Quickstart โ€” 3 commands

```bash
# 1. Install (one tarball, both binaries)
npm i -g @neatcodeai/cli

# 2. Index your repo
cd ~/your/typescript/repo
neatcode init

# 3. Wire it into Claude Code
neatcode claude install
```

Restart Claude Code. Your agent now has 11 structural tools โ€” and a fresh `.neatcode/REPO_OVERVIEW.md` for instant context.

> ๐ŸŽฏ **Founder's target:** *installed in 10 minutes, useful in 1 hour.*

### ๐ŸŽฌ What it looks like in practice

```text
๐Ÿ‘ค You: "Where do we handle booking cancellation?"

๐Ÿค– Agent: [calls query_graph with "booking cancellation"]
       โ†“
       ๐Ÿ“ BookingsController.cancel       (apps/api/src/bookings/โ€ฆ)
       ๐Ÿ“ BookingsService.cancel          (called by Controller)
       ๐Ÿ“ RefundService.issueRefund       (called by Service)
       ๐Ÿ“ BookingCancelledEvent           (emitted at end)

       Here's the flow: Controller โ†’ Service โ†’ RefundService,
       with a domain event published on completion.
```

vs. without neatcode: agent runs 4 grep calls, reads 18 files, and still misses the event publisher.

---

## ๐Ÿ”ท TypeScript compatibility

neatcode ships TypeScript types and is built around `ts-morph`. It indexes any TypeScript codebase that compiles.

| What | Compatibility |
| --- | --- |
| TypeScript versions | `5.0` โ†’ `5.7+` (uses `ts-morph` 24.x; tracks the bundled compiler) |
| File extensions | `.ts`, `.tsx` (skips `.d.ts` and `.generated.ts(x)`); `.js` / `.cjs` not yet indexed |
| Module systems | ESM, CommonJS, mixed โ€” output target doesn't matter |
| `tsconfig.json` | Auto-detected at repo root; respects `paths`, `baseUrl`, `composite` |
| JSX / TSX | Yes โ€” `.tsx` parsed, JSX edges emitted |
| Decorators | Stage-3 standard + experimental (NestJS, TypeORM, class-validator) |
| Type-aware queries | Uses TS TypeChecker for cross-file call-graph resolution |
| Strict mode | Recommended but not required |
| Monorepos | pnpm / yarn / npm workspaces โ€” each package gets its own `qualified_name` namespace |
| Frameworks | NestJS, React, Next.js, Express, Fastify (auto-detected; no rule packs) |

Not on TypeScript? neatcode v0.1 is TS-only by design โ€” Python, Go, and JS support are roadmapped (see [Roadmap](#roadmap)).

---

## โšก CLI reference

```text
neatcode <command> [options]
```

### ๐Ÿ“ฅ Indexing

| Command | What it does |
| --- | --- |
| `neatcode init` | First-time setup. Creates `.neatcode/`, indexes every `.ts`/`.tsx` file, runs the heuristic miner, drops `REPO_OVERVIEW.md`. |
| `neatcode sync [--force]` | Re-index changed files. Content-hash cached โ€” editing 3 files re-parses 3 files. |
| `neatcode ask "<question>"` | Ad-hoc graph query from the terminal. Same engine as `query_graph` over MCP. |

### ๐ŸŽ“ Skills (conventions)

| Command | What it does |
| --- | --- |
| `neatcode skills derive [--threshold 0.85] [--min-population 3]` | Mine the graph for high-coverage patterns. Writes `skills.candidates.yaml`. |
| `neatcode skills accept <id> [--all] [--confidence high\|medium] [--local]` | Promote candidates into `skills.yaml` (committed) or `skills.local.yaml` (gitignored). |
| `neatcode skills reject <id> [--reason "โ€ฆ"]` | Mark a candidate as rejected so the next `derive` skips it. |

### โœ… Validation

| Command | What it does |
| --- | --- |
| `neatcode validate [<filesโ€ฆ>] [--json]` | No args โ†’ check whole graph. With files โ†’ treat as planned diff. Pre-existing offenders are grandfathered under `scope: "new"`. |
| `neatcode exception add <rule_id> <location> [--days N] [--reason "โ€ฆ"]` | Silence a specific violation. Auto-expires with `--days`. |
| `neatcode exception list` | Show active exceptions. |
| `neatcode exception revoke <rule_id> <location>` | Append-only revoke (original entry preserved). |

### ๐Ÿ”Œ Editor integration

| Command | What it does |
| --- | --- |
| `neatcode claude install` | Merges `.mcp.json`, appends MCP guidance to `CLAUDE.md`. Idempotent. |
| `neatcode claude uninstall` | Reverses both. Pre-existing CLAUDE.md content is preserved. |
| `neatcode cursor install` *(coming v0.2)* | Wires neatcode-mcp into Cursor's MCP config. |
| `neatcode codex install` *(coming v0.2)* | Wires neatcode-mcp into Codex. |

---

## ๐Ÿ”— MCP integration

The agent gets 11 tools the moment Claude Code restarts after `neatcode claude install`:

**Discovery + queries**

| Tool | When the agent calls it |
| --- | --- |
| `get_repo_overview` | Once per session. Returns frameworks, top symbols, layout, active rules, dirty-file status. |
| `query_graph` | "What handles X?", "what calls Y?" โ€” keyword-scored search with optional 1-hop expansion. |
| `find_node` | Exact lookup by name or `qualified_name`. Returns merged class+method decorators. |
| `trace_flow` | Multi-hop path traversal. "From `BookingsController.create` to the DB" returns the call chain. |

**Rules + validation**

| Tool | When the agent calls it |
| --- | --- |
| `get_rules` | Returns active rules, candidates, rejected list, and repo context for curation flows. |
| `validate_diff` | Pre-flight on a planned change. Returns violations + four-option suggestions block. |
| `propose_rule_from_prompt` | Inspects a user utterance for rule-language ("never", "must", "always"). Surfaces a structured proposal. |
| `accept_proposed_rule` | Promote a single proposed rule into `skills.yaml`. |
| `derive_candidates` | Run the heuristic miner on demand and return candidate rules. |
| `accept_derived_candidates` | Bulk-accept miner candidates by id, confidence, or `--all`. |

**Memory**

| Tool | When the agent calls it |
| --- | --- |
| `add_note` | Persist a fact the user shared. Appends to `.neatcode/memory/notes-YYYY-MM-DD.md`. |

All deterministic. No LLM call inside the server. The agent is the brain; neatcode is the spine.

---

## ๐Ÿ“‚ What lives in `.neatcode/`

`neatcode init` creates the directory and seeds it with the indexer output and miner proposals. The remaining files appear on demand as you accept rules, record exceptions, and let the agent take notes.

**Created by `neatcode init`:**

```text
<repo-root>/
โ”œโ”€โ”€ .neatcodeignore                team-shared excludes (commit it)
โ””โ”€โ”€ .neatcode/
    โ”œโ”€โ”€ graph.db                   SQLite graph         (regenerate; should gitignore)
    โ”œโ”€โ”€ skills.candidates.yaml     miner proposals      (regenerated each sync)
    โ”œโ”€โ”€ REPO_OVERVIEW.md           session-start brief  (commit it)
    โ”œโ”€โ”€ plans/                     /writing-plans skill scaffold (commit it)
    โ””โ”€โ”€ specs/                     /brainstorming skill scaffold (commit it)
```

**Appears on demand:**

```text
.neatcode/
โ”œโ”€โ”€ skills.yaml                   on first `skills accept`              (commit it)
โ”œโ”€โ”€ skills.local.yaml             on `skills accept --local`            (should gitignore)
โ”œโ”€โ”€ skills.rejected.yaml          on first `skills reject`              (commit it)
โ”œโ”€โ”€ decisions.yaml                on first exception/supersede          (commit it)
โ”œโ”€โ”€ memory/                       on first `add_note` MCP call          (commit it)
โ””โ”€โ”€ mcp.log                       on first MCP server start             (should gitignore)
```

> โ„น๏ธ `neatcode init` doesn't touch your `.gitignore`. Add the regeneratable bits yourself:
> ```gitignore
> .neatcode/graph.db*
> .neatcode/skills.candidates.yaml
> .neatcode/skills.local.yaml
> .neatcode/mcp.log
> ```

`graph.db` is regeneratable from a single `neatcode sync`. The committed files above form the team-shared memory of the repo โ€” that's the part you code-review.

---

## ๐Ÿ“ How rules emerge

Three sources, one lifecycle:

1. **Heuristic mining** โ€” `neatcode skills derive` proposes candidates above the coverage threshold. Four primitives mined today: `decorator-required`, `annotation-forbidden`, `naming-pattern`, `folder-naming-convention`.
2. **Prompts** โ€” when the user says *"all classes with @Controller must use @UseGuards"*, the agent calls `propose_rule_from_prompt`. A local keyword classifier โ€” **no LLM in the loop** โ€” extracts a structured candidate. User confirms, agent runs `skills accept`.
3. **Manual** โ€” hand-edit `.neatcode/skills.yaml` (create it on first rule). The schema is documented and stable.

Rules are validated **bidirectionally**:
- A diff that violates a rule โ†’ four-option UX (record exception ยท time-bounded ยท supersede the rule ยท abort).
- A rule that no longer matches the codebase โ†’ can be superseded with an entry in `decisions.yaml`.

### ๐Ÿงฉ The six primitives

| Primitive | Mined? | Example |
| --- | :-: | --- |
| `decorator-required` | yes | classes with `@ApiTags` must also have `@Controller` |
| `annotation-forbidden` | yes | classes with `@Controller` must not carry `@Deprecated` |
| `naming-pattern` | yes | classes with `@Module` end with `"Module"` |
| `folder-naming-convention` | yes | files in `apps/api/services/` end with `.service.ts` |
| `import-forbidden` | via prompt | `never import from packages/internal/` |
| `edge-forbidden` | via prompt | `controllers must not call repositories directly` |

Layer constraints (*"controllers can't reach repositories"*) are expressed via `edge-forbidden` โ€” no special "layer" type.

### ๐ŸŒฑ Default rule scope: `new`

Rules default to `scope: "new"` โ€” pre-existing violations are **grandfathered**. Only code introduced *after* the rule was promoted gets checked. Set `scope: "all"` in YAML to enforce against existing code.

This avoids the classic *"we accepted 30 conventions and now CI is on fire"* problem.

---

## ๐Ÿ—๏ธ Architecture

```text
       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
       โ”‚  ๐Ÿ“œ ts-morph parser  โ”€โ”€โ–ถ  ๐Ÿ—‚๏ธ  polymorphic graph  โ”‚
       โ”‚                              (SQLite)            โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                             โ”‚
       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
       โ–ผ                     โ–ผ                     โ–ผ
  ๐Ÿ” query_graph        ๐ŸŽ“ skills derive      โœ… validate_diff
  ๐Ÿ“ find_node          (heuristic miner)        (engine.ts)
  ๐Ÿ›ค๏ธ trace_flow                โ”‚                       โ”‚
       โ”‚                       โ–ผ                       โ–ผ
       โ”‚                skills.candidates      active rules โˆฉ
       โ”‚                    โ†’ accept           decisions.yaml
       โ–ผ                                              โ”‚
  ๐Ÿค– agent answers โ—€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  โš ๏ธ violations
                                              + 4-option UX
```

Every relationship gets a confidence label (`EXTRACTED` | `INFERRED` | `AMBIGUOUS`); the validator **never fires on rules built solely from `AMBIGUOUS` edges**. The repo-root-relative `qualified_name` is the FK that ties nodes, edges, rules, and decisions together. There's no LLM in the hot path of any MCP tool โ€” the LLM lives in the agent harness (Claude Code, Cursor, Codex), and neatcode is the spine.

---

## ๐Ÿ“ฆ Packages

The CLI bundles everything you need; the others are split for advanced use.

| Package | Install for | What it gives you |
| --- | --- | --- |
| [`@neatcodeai/cli`](https://www.npmjs.com/package/@neatcodeai/cli) | Most users | `neatcode` + `neatcode-mcp` binaries (depends on the others). |
| [`@neatcodeai/mcp`](https://www.npmjs.com/package/@neatcodeai/mcp) | Bare MCP server | The stdio MCP binary alone. |
| [`@neatcodeai/core`](https://www.npmjs.com/package/@neatcodeai/core) | Library users | `parseFile`, `Database`, `ask`, miner โ€” all typed. |

Single install gets you everything:

```bash
npm i -g @neatcodeai/cli
which neatcode neatcode-mcp
```

---

## ๐Ÿ› ๏ธ Develop

```bash
pnpm install           # builds better-sqlite3 native module
pnpm build             # builds all three packages
pnpm typecheck         # tsc --noEmit across packages
pnpm test              # vitest run
pnpm test:watch
pnpm clean

# Smoke-test
node packages/cli/dist/index.js --help
```

Node 20+, TypeScript strict + `verbatimModuleSyntax`, ESM only.

---

## ๐Ÿ—บ๏ธ Roadmap

- **v0.1** *(shipped)* โ€” TypeScript-only, 11 MCP tools, validation engine, four-option UX, heuristic miner with four primitives, Claude Code installer.
- **v0.2** โ€” Cursor + Codex installers, `import-forbidden` / `edge-forbidden` mining, agent-proposed rules (`skills derive --with-agent`).
- **v0.3** โ€” Watcher mode (`neatcode dev`), JavaScript / `.js` / `.cjs` indexing, TypeScript LSP integration.
- **Later** โ€” Python via `tree-sitter`, Go via `go/parser`, multi-language graphs joined by import-edge inference.

Issues, feature requests, and convention horror stories: [github.com/HitmanDark07/neatcodeai/issues](https://github.com/HitmanDark07/neatcodeai/issues).

---

## ๐Ÿ›ก๏ธ Hard rules (project guarantees)

- No framework rule packs โ€” conventions emerge per-repo.
- Decorators / generics / JSX live in `extra` JSON, not schema columns.
- `qualified_name` is **always** repo-root-relative.
- Rules built solely on `AMBIGUOUS` edges never enforce.
- v0.1 doesn't solve general NestJS DI โ€” `@Module({ providers, controllers, imports })` arrays become direct edges and we stop there.

---

<div align="center">

### ๐Ÿ“„ License

[MIT](./LICENSE) ยท built with โค๏ธ by [@HitmanDark07](https://github.com/HitmanDark07)

โญ *If neatcode helps your agent stop guessing, star the repo.*

</div>