Skip to content

Latest commit

 

History

History
123 lines (88 loc) · 6.17 KB

File metadata and controls

123 lines (88 loc) · 6.17 KB

aiscope: see what your AI tools actually believe about your code

A 5MB Rust CLI that diffs Cursor / Claude Code / GitHub Copilot context files and tells you exactly where they disagree.

The problem nobody owns

You have .cursorrules. You have .github/copilot-instructions.md. You have CLAUDE.md. You have .github/instructions/python.instructions.md. You have .github/agents/reviewer.agent.md. Maybe a .claude/skills/ folder. Maybe an apps/web/AGENTS.md because the web team wanted their own conventions.

Every one of them is a markdown file. Every one of them is silently shoved into the model's context window. None of them know about each other.

So you end up shipping code where:

  • One file says "use snake_case", another says "use camelCase".
  • The agent allowlist says tools: [read, search] but your instructions say "use the bash tool to run pytest".
  • Two files repeat the exact same sentence in slightly different words — burning tokens to tell the model the same thing twice.
  • A python.instructions.md (applyTo: **/*.py) and a typescript.instructions.md (applyTo: **/*.ts) look like a contradiction but actually never apply to the same file. False alarm.

You have no tool that knows the difference. Until now.

What aiscope does

aiscope is a single Rust binary that:

  1. Discovers every memory file across all 3 major coding-AI tools — Cursor, Claude Code, GitHub Copilot — and across all 5 subsystems each of them supports: instructions, prompts, agents, chat modes, skills.
  2. Parses the YAML frontmatter (applyTo, globs, alwaysApply, tools:, model:) so it understands scope, not just text.
  3. Extracts assertions on canonical axes: indentation style, naming convention, quote style, package manager, etc.
  4. Reasons about pairs: do they overlap in scope? Do they contradict? Is this a real high-severity clash, or just two non-overlapping rules that happen to disagree?
  5. Renders as a ratatui-style TUI, a miette compiler diagnostic, JSON, or a 1280×720 PNG card you can drop into a PR or tweet.
$ aiscope .
aiscope · my-repo · 8% wasted
6 sources · 18 rules · 14 clashes · 1 duplicates · 159 tokens

  [HIGH agent]  .github/agents/reviewer.agent.md ⇄ .github/instructions/python.instructions.md
                says "use the bash tool" but agent excludes it
  [HIGH clash]  .github/copilot-instructions.md ⇄ apps/web/AGENTS.md
                4 spaces disagrees with 2 spaces
  [HIGH clash]  .github/copilot-instructions.md ⇄ .github/instructions/python.instructions.md
                camelCase disagrees with snake_case
  +12 more...

Two reasoning modes

Because not everyone agrees on whether prompts and instructions should contradict (a prompt is one-shot; an instruction is permanent), aiscope ships two modes:

  • Uniform (default) — every cross-source pair is a candidate. Maximum recall.
  • Specific (--specific) — uses a subsystem-clash matrix:
    • Prompts ↔ Instructions: never conflict (prompts are intentional overrides).
    • Agents ↔ everything else: never conflict (agents have their own context).
    • Skills / ChatModes ↔ anything: never conflict.

Pick whichever matches how your team actually uses the files.

Scope-aware severity

The killer feature: aiscope reads the applyTo glob and uses globset to compute whether two scopes overlap.

  • applyTo: **/*.py and applyTo: **/*.tsdon't overlap → severity demoted to Low with a (scopes don't overlap) note. It's not actually a clash.
  • applyTo: **/*.py and root copilot-instructions.md (no applyTo, applies everywhere) — overlap → High severity. This will hit the model at the same time and confuse it.

Same for apps/web/AGENTS.md — automatically scoped to apps/web/** because that's where it lives.

The Copilot-only case (one tool, all subsystems)

If your repo only has .github/, aiscope still earns its keep. A typical Copilot setup has:

.github/
├── copilot-instructions.md        ← applies everywhere
├── instructions/
│   ├── python.instructions.md     ← applyTo: **/*.py
│   └── typescript.instructions.md ← applyTo: **/*.ts
├── prompts/
│   └── unit-test.prompt.md        ← one-shot
└── agents/
    └── reviewer.agent.md          ← tools: [read, search]
apps/web/AGENTS.md                 ← path-scoped to apps/web/**

aiscope discovers all 6, parses every frontmatter field, and tells you which conflicts actually matter. It treats AGENTS.md as path-scoped automatically — a convention that should be obvious but no other tool does this for you.

Architecture (for the curious)

A 6-layer deterministic pipeline, each layer pure and testable:

scanner → frontmatter → md-parse → canon → extract → reason → render
  • scanner — WalkDir-based discovery per tool, with privacy guard (no reads outside the repo unless --user is passed, never CLAUDE.md transcripts)
  • frontmatter — hand-rolled YAML subset parser (no serde_yaml, no libyaml dep)
  • canon — NFKC + smart-quote/dash normalization + light stemming
  • extract — pattern-based assertion extraction onto typed axes (Naming(Variables), Indentation, QuoteStyle, …)
  • reason — pair-wise checks with subsystem matrix + scope overlap + severity demotion + duplicate-name detection across agents/skills/chatmodes
  • render — ratatui TUI, miette diagnostics, JSON, or PNG card with embedded JetBrains Mono

42 tests. Clippy -D warnings clean. ~5 MB release binary.

Install & try

cargo install --git https://github.com/Jayanth-MKV/aiscope
cd your-repo
aiscope .                # interactive TUI
aiscope --text .         # plain text
aiscope --diag .         # compiler-style diagnostics
aiscope --json .         # for CI / scripts
aiscope --card out.png . # 1280×720 PNG summary
aiscope check .          # exits non-zero if HIGH conflicts found (CI gate)

CI integration:

- run: cargo install aiscope
- run: aiscope check --specific .

That's it. Try it on your repo. You will probably find a conflict. We did.

github.com/Jayanth-MKV/aiscope