nogrep 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nogrep",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Navigable codebase index for Claude Code — stop grepping, start navigating",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,239 +0,0 @@
1
- # nogrep — Internal Architecture
2
-
3
- ## Module Boundaries
4
-
5
- ```
6
- ┌──────────────────────────────────────────────────────┐
7
- │ CC Plugin (slash commands) │
8
- │ /init · /update · /query · /status · /on · /off │
9
- │ Claude orchestrates — AI work happens here │
10
- └────────────────────────┬─────────────────────────────┘
11
- │ calls scripts via Bash
12
- ┌───────────────┼───────────────┐
13
- ▼ ▼ ▼
14
- ┌─────────────┐ ┌─────────────┐ ┌──────────────┐
15
- │ Signals │ │ Query │ │ Settings │
16
- │ (collect) │ │ (lookup) │ │ (r/w JSON) │
17
- └─────────────┘ └──────┬──────┘ └──────────────┘
18
-
19
- ┌─────────────┐ ┌──────┴──────┐
20
- │ Writer │ │ Validator │
21
- │ (file I/O) │ │ (freshness) │
22
- └─────────────┘ └─────────────┘
23
- ```
24
-
25
- No AI client module — Claude IS the AI. The slash commands contain the analysis prompts, and Claude executes them directly during the session.
26
-
27
- ---
28
-
29
- ## Module Responsibilities
30
-
31
- ### `commands/` (slash commands)
32
- Markdown prompts that guide Claude through each operation. `init.md` is the most complex — it orchestrates the full pipeline. Claude reads script output, performs analysis, and writes results.
33
-
34
- ### `scripts/signals.ts`
35
- Collects language-agnostic signals from the filesystem. Pure data collection — no AI, no writes to `.nogrep/`.
36
-
37
- ```typescript
38
- collectSignals(root, options) → SignalResult
39
- ```
40
-
41
- ### `scripts/write.ts`
42
- All file I/O for the `.nogrep/` directory. Takes structured JSON input (from Claude's analysis), writes files.
43
-
44
- ```typescript
45
- writeContextFiles(nodes: NodeResult[], outputDir: string) → void
46
- buildIndex(nodes: NodeResult[]) → IndexJson
47
- buildRegistry(nodes: NodeResult[]) → RegistryJson
48
- patchClaudeMd(projectRoot: string) → void
49
- ```
50
-
51
- ### `scripts/query.ts`
52
- Pure lookup logic. Reads `_index.json`, matches tags/keywords, ranks results. No AI, no file writes. Called by hooks and `/nogrep:query`.
53
-
54
- ```typescript
55
- extractTerms(question: string, taxonomy: Taxonomy) → { tags, keywords }
56
- resolve(terms, index) → RankedResult[]
57
- ```
58
-
59
- ### `scripts/validate.ts`
60
- Computes SHA256 of `src_paths` contents, compares to stored `src_hash` in node frontmatter.
61
-
62
- ```typescript
63
- checkFreshness(node: ContextNode, projectRoot: string) → StaleResult
64
- ```
65
-
66
- ### `scripts/settings.ts`
67
- Read/write `.claude/settings.json` and `.claude/settings.local.json`. Handles merge logic (local takes precedence).
68
-
69
- ---
70
-
71
- ## Data Flow: `/nogrep:init`
72
-
73
- > `$PLUGIN` = `${CLAUDE_PLUGIN_ROOT}` — the absolute path to the installed plugin directory.
74
-
75
- ```
76
- Slash command: init.md (Claude orchestrates)
77
-
78
- ├─→ Bash: node $PLUGIN/dist/signals.js → SignalResult (JSON stdout)
79
-
80
- ├─→ Claude analyzes signals → StackResult
81
-
82
- ├─→ For each cluster:
83
- │ Claude reads trimmed source → NodeResult
84
-
85
- ├─→ Claude detects flows → FlowResult[]
86
-
87
- └─→ Bash: node $PLUGIN/dist/write.js (receives JSON stdin)
88
- writes .nogrep/domains/*.md etc
89
- writes .nogrep/_index.json
90
- writes .nogrep/_registry.json
91
- patches CLAUDE.md
92
- writes .claude/settings.json
93
- ```
94
-
95
- ---
96
-
97
- ## Data Flow: Hooks
98
-
99
- ```
100
- User types prompt
101
-
102
- └─→ prompt-submit.sh
103
- node $PLUGIN/dist/query.js --question "$PROMPT"
104
- → injects additionalContext
105
-
106
- CC decides to run grep
107
-
108
- └─→ pre-tool-use.sh (PreToolUse hook)
109
- extracts keywords from grep command
110
- node $PLUGIN/dist/query.js --keywords "$KEYWORDS"
111
- → injects additionalContext
112
-
113
- CC starts session
114
-
115
- └─→ session-start.sh (SessionStart hook)
116
- node $PLUGIN/dist/validate.js
117
- → injects staleness warning if needed
118
- ```
119
-
120
- ---
121
-
122
- ## Key Types (`scripts/types.ts`)
123
-
124
- ```typescript
125
- export interface SignalResult {
126
- directoryTree: DirectoryNode[]
127
- extensionMap: Record<string, number>
128
- manifests: ManifestFile[]
129
- entryPoints: string[]
130
- gitChurn: ChurnEntry[]
131
- largeFiles: FileSize[]
132
- envFiles: string[]
133
- testFiles: string[]
134
- }
135
-
136
- export interface StackResult {
137
- primaryLanguage: string
138
- frameworks: string[]
139
- architecture: 'monolith' | 'monorepo' | 'multi-repo' | 'microservice' | 'library'
140
- domainClusters: DomainCluster[]
141
- conventions: StackConventions
142
- stackHints: string
143
- dynamicTaxonomy: { domain: string[]; tech: string[] }
144
- }
145
-
146
- export interface DomainCluster {
147
- name: string
148
- path: string
149
- confidence: number
150
- }
151
-
152
- export interface NodeResult {
153
- id: string
154
- title: string
155
- category: 'domain' | 'architecture' | 'flow' | 'entity'
156
- tags: TagSet
157
- relatesTo: Relation[]
158
- inverseRelations: Relation[]
159
- srcPaths: string[]
160
- keywords: string[]
161
- lastSynced: SyncMeta
162
- // content fields
163
- purpose: string
164
- publicSurface: string[]
165
- doesNotOwn: string[]
166
- externalDeps: ExternalDep[]
167
- gotchas: string[]
168
- }
169
-
170
- export interface TagSet {
171
- domain: string[]
172
- layer: string[]
173
- tech: string[]
174
- concern: string[]
175
- type: string[]
176
- }
177
-
178
- export interface IndexJson {
179
- version: string
180
- generatedAt: string
181
- commit: string
182
- stack: Pick<StackResult, 'primaryLanguage' | 'frameworks' | 'architecture'>
183
- tags: Record<string, string[]>
184
- keywords: Record<string, string[]>
185
- paths: Record<string, PathEntry>
186
- }
187
-
188
- export interface RankedResult {
189
- contextFile: string
190
- score: number
191
- matchedOn: string[]
192
- summary: string
193
- }
194
-
195
- export interface StaleResult {
196
- file: string
197
- isStale: boolean
198
- reason?: string
199
- }
200
- ```
201
-
202
- ---
203
-
204
- ## Error Handling Strategy
205
-
206
- - Scripts: throw typed errors (`NogrepError` with `code` field), exit 1 with JSON error on stderr
207
- - Hooks: fail silently (exit 0) — never block CC session
208
- - Never swallow errors silently in scripts
209
-
210
- ```typescript
211
- export class NogrepError extends Error {
212
- constructor(
213
- message: string,
214
- public code: 'NO_INDEX' | 'NO_GIT' | 'IO_ERROR' | 'STALE'
215
- ) {
216
- super(message)
217
- }
218
- }
219
- ```
220
-
221
- ---
222
-
223
- ## Testing Strategy
224
-
225
- ### Unit tests (no filesystem)
226
- - `query/extractor.test.ts` — NL extraction logic
227
- - `query/resolver.test.ts` — index lookup ranking
228
- - `validator/staleness.test.ts` — hash comparison logic
229
- - `settings/index.test.ts` — merge logic
230
-
231
- ### Integration tests (real filesystem)
232
- - `signals.test.ts` — run against fixture projects
233
- - `writer/*.test.ts` — write to temp dir, verify file contents
234
-
235
- ### Fixture projects (`tests/fixtures/`)
236
- Minimal 5-10 file projects, enough for signal detection:
237
- - `nestjs-project/` — NestJS with billing + auth modules
238
- - `django-project/` — Django with users + payments apps
239
- - `react-project/` — React app with auth + dashboard features
package/docs/CLAUDE.md DELETED
@@ -1,161 +0,0 @@
1
- # nogrep — Implementation Guide for Claude Code
2
-
3
- ## What You Are Building
4
-
5
- `nogrep` is a Claude Code plugin that gives AI agents a navigable index of any codebase, so they stop doing blind grep/find exploration.
6
-
7
- **The one thing it does:** Generate and maintain a structured `.nogrep/` directory with a reverse index (`_index.json`) and thin context nodes (markdown files), so CC can find the right files in 2 reads instead of 20.
8
-
9
- **What it is NOT:** A documentation generator, a code search engine, a standalone CLI, or a replacement for GSD or Compodoc. It is a navigation layer — intentionally minimal, fully scoped to Claude Code.
10
-
11
- ---
12
-
13
- ## Before You Start
14
-
15
- Read these files in order before writing any code:
16
-
17
- 1. `docs/SPEC.md` — full technical specification, schemas, pipeline details
18
- 2. `docs/ARCHITECTURE.md` — project structure and module boundaries
19
- 3. `docs/CONVENTIONS.md` — code style, naming, patterns to follow
20
-
21
- ---
22
-
23
- ## Project Stack
24
-
25
- - **Language:** TypeScript (strict mode)
26
- - **Runtime:** Node.js 20+
27
- - **Package manager:** npm
28
- - **Testing:** Vitest
29
- - **Build:** `tsup`
30
- - **Distribution:** CC plugin (npm package)
31
-
32
- ---
33
-
34
- ## Repository Structure to Create
35
-
36
- ```
37
- nogrep/
38
- ├── scripts/
39
- │ ├── signals.ts # Phase 1: universal signal collection
40
- │ ├── query.ts # index lookup (called by hooks)
41
- │ ├── validate.ts # staleness check (called by hooks)
42
- │ ├── write.ts # structured file writer (context nodes, index, registry)
43
- │ ├── settings.ts # read/write .claude/settings.json
44
- │ ├── trim.ts # language-agnostic source trimming
45
- │ └── types.ts # all shared TypeScript types
46
- ├── commands/
47
- │ ├── init.md # orchestrates full init pipeline
48
- │ ├── update.md # diff-based update of stale nodes
49
- │ ├── query.md # manual index lookup
50
- │ ├── status.md # coverage + freshness summary
51
- │ ├── on.md # enable nogrep
52
- │ └── off.md # disable nogrep
53
- ├── hooks/
54
- │ ├── pre-tool-use.sh # intercepts grep/find/rg
55
- │ ├── session-start.sh # checks index freshness on session start
56
- │ └── prompt-submit.sh # injects context on every user prompt
57
- ├── templates/
58
- │ └── claude-md-patch.md # snippet appended to target project CLAUDE.md
59
- ├── tests/
60
- │ ├── fixtures/ # sample mini-projects for testing
61
- │ │ ├── nestjs-project/
62
- │ │ ├── django-project/
63
- │ │ └── react-project/
64
- │ ├── signals.test.ts
65
- │ ├── query.test.ts
66
- │ └── writer.test.ts
67
- ├── docs/
68
- │ ├── CLAUDE.md # this file
69
- │ ├── SPEC.md # full technical spec
70
- │ ├── ARCHITECTURE.md # internal architecture doc
71
- │ ├── CONVENTIONS.md # coding conventions
72
- │ └── TASKS.md # implementation tasks
73
- ├── plugin.json
74
- ├── package.json
75
- ├── tsconfig.json
76
- └── README.md
77
- ```
78
-
79
- ---
80
-
81
- ## Implementation Order
82
-
83
- Implement in this exact order — each step is testable before moving on:
84
-
85
- ### Step 1 — Scaffold
86
- - `package.json`, `tsconfig.json`, `tsup.config.ts`
87
- - `scripts/types.ts` — all types first
88
- - `plugin.json` — CC plugin manifest
89
-
90
- ### Step 2 — Settings
91
- - `scripts/settings.ts` — read/write `.claude/settings.json` and `.claude/settings.local.json`
92
- - `commands/on.md` and `commands/off.md` slash commands
93
-
94
- ### Step 3 — Phase 1: Signals (no AI)
95
- - `scripts/signals.ts` — universal signal collection
96
- - Test against the fixtures in `tests/fixtures/`
97
-
98
- ### Step 4 — Source Trimming
99
- - `scripts/trim.ts` — language-agnostic source trimming
100
- - Test against TypeScript, Python, Java snippet fixtures
101
-
102
- ### Step 5 — Writers
103
- - `scripts/write.ts` — context files, index builder, registry, CLAUDE.md patcher
104
- - `templates/claude-md-patch.md`
105
- - Test: write to temp dirs, verify file contents
106
-
107
- ### Step 6 — Init Slash Command
108
- - `commands/init.md` — orchestrates the full pipeline
109
- - Embeds Phase 2 + Phase 3 prompts (Claude does the AI work)
110
- - Calls `dist/signals.js` for data, `dist/write.js` for output via `${CLAUDE_PLUGIN_ROOT}`
111
-
112
- ### Step 7 — Query System
113
- - `scripts/query.ts` — extractor + resolver
114
- - `commands/query.md` slash command
115
-
116
- ### Step 8 — Validate + Update + Status
117
- - `scripts/validate.ts` — staleness detection
118
- - `commands/update.md` — guided incremental update
119
- - `commands/status.md` — index health summary
120
-
121
- ### Step 9 — Hooks
122
- - `hooks/pre-tool-use.sh` — intercepts grep/find
123
- - `hooks/session-start.sh` — freshness check
124
- - `hooks/prompt-submit.sh` — context injection
125
-
126
- ### Step 10 — README + Distribution
127
- - `README.md`
128
- - Verify `npm pack` ships correct files
129
-
130
- ---
131
-
132
- ## Key Decisions Already Made
133
-
134
- - **No standalone CLI.** Everything runs inside CC via slash commands and hooks.
135
- - **No AI client / SDK.** Claude IS the AI — slash commands contain the analysis prompts, Claude executes them directly.
136
- - **No database.** Everything is files. `.nogrep/` lives in the repo.
137
- - **Scripts are mechanical.** They collect data, write files, query indexes — no AI work.
138
- - **Nodes are intentionally thin** — 3 sentences of purpose, public surface, does-not-own, gotchas. Not comprehensive docs.
139
- - **Manual Notes section** in each node is never overwritten by update.
140
- - **Hooks intercept at tool-call level** — not just CLAUDE.md instructions, so CC cannot bypass.
141
- - **Per-project settings** — `.claude/settings.json` (team, committed) or `.claude/settings.local.json` (personal, gitignored).
142
- - **CI is out of scope for v1** — index maintained via `/nogrep:update` during CC sessions.
143
-
144
- ---
145
-
146
- ## Environment Variables
147
-
148
- ```bash
149
- NOGREP_DEBUG # optional, set to 1 for verbose script output
150
- ```
151
-
152
- No `ANTHROPIC_API_KEY` needed — Claude does the AI work directly.
153
-
154
- ---
155
-
156
- ## Testing Approach
157
-
158
- - Use **Vitest** for all tests
159
- - Fixture projects in `tests/fixtures/` are minimal — 5-10 files each, enough to test detection
160
- - No AI mocking needed — scripts are pure data/IO
161
- - Run: `npm test`
@@ -1,162 +0,0 @@
1
- # nogrep — Coding Conventions
2
-
3
- ## Language & Runtime
4
-
5
- - TypeScript strict mode — `"strict": true` in tsconfig
6
- - Node.js 20+
7
- - ESM modules (`"type": "module"` in package.json)
8
- - No `any` — use `unknown` and narrow
9
-
10
- ---
11
-
12
- ## Naming
13
-
14
- ```typescript
15
- // Files: kebab-case
16
- signals.ts
17
- index-builder.ts
18
- pre-tool-use.sh
19
-
20
- // Types/Interfaces: PascalCase
21
- interface StackResult { ... }
22
- interface NodeResult { ... }
23
-
24
- // Functions: camelCase, verb-first
25
- collectSignals()
26
- buildIndex()
27
- resolveQuery()
28
- extractTerms()
29
- checkFreshness()
30
-
31
- // Constants: UPPER_SNAKE_CASE
32
- const MAX_CLUSTER_LINES = 300
33
- ```
34
-
35
- ---
36
-
37
- ## Functions
38
-
39
- - Small and focused — one responsibility
40
- - Pure functions where possible (especially in scripts)
41
- - Prefer named parameters for 3+ args:
42
-
43
- ```typescript
44
- // ✅
45
- writeContextFiles({ nodes, outputDir, preserveManualNotes })
46
-
47
- // ❌
48
- writeContextFiles(nodes, outputDir, true)
49
- ```
50
-
51
- - Always type return values explicitly on exported functions
52
- - Async/await everywhere — no raw Promise chains
53
-
54
- ---
55
-
56
- ## Error Handling
57
-
58
- Always use `NogrepError` with a code for expected failures:
59
-
60
- ```typescript
61
- // ✅
62
- throw new NogrepError('No .nogrep/_index.json found. Run /nogrep:init first.', 'NO_INDEX')
63
-
64
- // ❌
65
- throw new Error('not found')
66
- ```
67
-
68
- Scripts catch `NogrepError` and output JSON errors to stderr.
69
- Hooks fail silently (exit 0) — never block the CC session.
70
-
71
- ---
72
-
73
- ## File I/O
74
-
75
- - All file paths are absolute — resolve early, pass around as absolute
76
- - Use `fs/promises` — no sync fs calls
77
- - Writer functions take `outputDir` as explicit parameter — never hardcode `.nogrep/`
78
-
79
- ---
80
-
81
- ## Script Output
82
-
83
- Scripts communicate via stdout (JSON for data, plain text for human-readable).
84
-
85
- ```
86
- # ✅ Good
87
- { "nodes": 17, "stale": 1 }
88
-
89
- # ❌ Too chatty
90
- 🚀 Starting signal collection...
91
- 📁 Found 42 files...
92
- ```
93
-
94
- Verbose output only when `NOGREP_DEBUG=1`, and goes to stderr.
95
-
96
- ---
97
-
98
- ## Package Structure
99
-
100
- ```json
101
- {
102
- "type": "module",
103
- "files": ["dist/", "commands/", "hooks/", "templates/", "plugin.json"]
104
- }
105
- ```
106
-
107
- ---
108
-
109
- ## Dependencies
110
-
111
- Keep dependencies minimal. Approved list:
112
-
113
- | Package | Purpose |
114
- |---------|---------|
115
- | `glob` | file glob matching |
116
- | `gray-matter` | frontmatter parsing |
117
- | `js-yaml` | YAML serialization |
118
- | `vitest` | testing (dev) |
119
- | `tsup` | build (dev) |
120
- | `typescript` | type checking (dev) |
121
- | `@types/node` | Node type defs (dev) |
122
-
123
- Do not add new dependencies without a strong reason.
124
-
125
- ---
126
-
127
- ## tsconfig.json
128
-
129
- ```json
130
- {
131
- "compilerOptions": {
132
- "target": "ES2022",
133
- "module": "ESNext",
134
- "moduleResolution": "bundler",
135
- "strict": true,
136
- "noUncheckedIndexedAccess": true,
137
- "outDir": "./dist",
138
- "rootDir": "./scripts",
139
- "declaration": true,
140
- "sourceMap": true
141
- },
142
- "include": ["scripts/**/*"],
143
- "exclude": ["node_modules", "dist", "tests"]
144
- }
145
- ```
146
-
147
- ---
148
-
149
- ## Tests
150
-
151
- - Test files in `tests/` directory
152
- - Use `describe` + `it` — not `test`
153
- - Each test file is independent — no shared state between files
154
- - Use `vitest`'s `vi.mock` sparingly — prefer dependency injection
155
-
156
- ```typescript
157
- // ✅ injectable
158
- const result = collectSignals('/path/to/fixture', { exclude: [] })
159
-
160
- // ❌ global mock
161
- vi.mock('fs/promises')
162
- ```