ucn 3.7.25 → 3.7.26
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/README.md +192 -463
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,403 +1,109 @@
|
|
|
1
|
-
# UCN
|
|
1
|
+
# UCN — Universal Code Navigator
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
AST-powered code intelligence from the terminal.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
UCN answers structural code questions instantly:
|
|
6
|
+
- Who calls this function?
|
|
7
|
+
- What breaks if I change this signature?
|
|
8
|
+
- What changed in this diff, and who depends on it?
|
|
9
|
+
- What code is safe to delete?
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
The ucn mcp is kept light, as all 28 commands ship as a single MCP tool, under 2k tokens total.
|
|
11
|
+
Instead of reading full files, UCN gives precise, AST-verified answers.
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
## What UCN does
|
|
13
|
-
|
|
14
|
-
Precise answers without reading files.
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
TASK COMMAND
|
|
18
|
-
───────────────────── ─────────────────────
|
|
19
|
-
|
|
20
|
-
Pull one function from $ ucn fn handleRequest
|
|
21
|
-
a 2000-line file → 20 lines, just that function
|
|
22
|
-
|
|
23
|
-
Who calls this? Will they $ ucn impact handleRequest
|
|
24
|
-
break if I change it? → 8 call sites, with arguments
|
|
25
|
-
|
|
26
|
-
What happens when $ ucn trace main --depth=3
|
|
27
|
-
main() runs? → full call tree, no file reads
|
|
28
|
-
|
|
29
|
-
What can I safely delete? $ ucn deadcode
|
|
30
|
-
→ unused functions, AST-verified
|
|
31
|
-
|
|
32
|
-
What depends on this file $ ucn graph src/routes.ts
|
|
33
|
-
before I move it? → imports and importers tree
|
|
34
|
-
```
|
|
13
|
+
[](https://www.npmjs.com/package/ucn)
|
|
14
|
+
[](LICENSE)
|
|
35
15
|
|
|
36
16
|
---
|
|
37
17
|
|
|
38
|
-
##
|
|
18
|
+
## 60-Second Quickstart
|
|
39
19
|
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
│ │
|
|
43
|
-
│ 1. CLI Use it directly from the terminal. │
|
|
44
|
-
│ $ ucn about myFunc Works standalone, no agent required. │
|
|
45
|
-
│ │
|
|
46
|
-
│ 2. MCP Server Any MCP-compatible AI agent connects │
|
|
47
|
-
│ $ ucn --mcp and gets 28 commands automatically. │
|
|
48
|
-
│ │
|
|
49
|
-
│ 3. Agent Skill Drop-in skill for Claude Code and │
|
|
50
|
-
│ /ucn about myFunc OpenAI Codex CLI. No server needed. │
|
|
51
|
-
│ │
|
|
52
|
-
└──────────────────────────────────────────────────────────────────────┘
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## How agents understand code today
|
|
58
|
-
|
|
59
|
-
AI agents working with code typically do this:
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g ucn
|
|
60
22
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
read file1.ts → 2000 lines... wrong function
|
|
66
|
-
│
|
|
67
|
-
▼
|
|
68
|
-
read file2.ts → 1500 lines... still not it
|
|
69
|
-
│
|
|
70
|
-
▼
|
|
71
|
-
read file3.ts → found it, finally
|
|
72
|
-
│
|
|
73
|
-
▼
|
|
74
|
-
grep "whoCallsThis" → start over
|
|
75
|
-
│
|
|
76
|
-
▼
|
|
77
|
-
┌─────────────────────────────────────────┐
|
|
78
|
-
│ Half the context window is gone. │
|
|
79
|
-
│ The agent hasn't changed a single line.│
|
|
80
|
-
└─────────────────────────────────────────┘
|
|
23
|
+
ucn about handleRequest # full picture: definition, callers, callees, tests
|
|
24
|
+
ucn impact handleRequest # all call sites with arguments
|
|
25
|
+
ucn trace main --depth=3 # call tree, no file reads
|
|
26
|
+
ucn deadcode # unused functions, AST-verified
|
|
81
27
|
```
|
|
82
28
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
## How UCN works: tree-sitter, locally
|
|
29
|
+
Parses JS/TS, Python, Go, Rust, Java, and HTML with tree-sitter. Runs locally.
|
|
86
30
|
|
|
87
31
|
```
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
│ 28 commands │
|
|
99
|
-
│ runs locally │
|
|
100
|
-
└────────┬──────────┘
|
|
101
|
-
│
|
|
102
|
-
tree-sitter AST
|
|
103
|
-
│
|
|
104
|
-
┌─────────────────┴───────────────────┐
|
|
105
|
-
│ Supported Languages │
|
|
106
|
-
│ JS/TS, Python, Go, Rust, Java, HTML │
|
|
107
|
-
└─────────────────────────────────────┘
|
|
32
|
+
Terminal AI Agents Agent Skills
|
|
33
|
+
│ │ │
|
|
34
|
+
CLI MCP Skill
|
|
35
|
+
└────────────────────┼───────────────────────┘
|
|
36
|
+
│
|
|
37
|
+
┌──────┴──────┐
|
|
38
|
+
│ UCN Engine │
|
|
39
|
+
│ 28 commands │
|
|
40
|
+
│ tree-sitter │
|
|
41
|
+
└─────────────┘
|
|
108
42
|
```
|
|
109
43
|
|
|
110
44
|
---
|
|
111
45
|
|
|
112
|
-
##
|
|
46
|
+
## Why UCN
|
|
113
47
|
|
|
114
|
-
|
|
115
|
-
WITHOUT UCN WITH UCN
|
|
116
|
-
────────────────────── ──────────────────────
|
|
117
|
-
|
|
118
|
-
grep "processOrder" ucn impact "processOrder"
|
|
119
|
-
│ │
|
|
120
|
-
▼ ▼
|
|
121
|
-
34 matches, mostly noise 8 call sites, grouped by file,
|
|
122
|
-
│ with actual arguments passed
|
|
123
|
-
▼ │
|
|
124
|
-
read service.ts (800 lines) │
|
|
125
|
-
│ │
|
|
126
|
-
▼ │
|
|
127
|
-
read handler.ts (600 lines) ucn smart "processOrder"
|
|
128
|
-
│ │
|
|
129
|
-
▼ ▼
|
|
130
|
-
read batch.ts (400 lines) function + all dependencies
|
|
131
|
-
│ expanded inline
|
|
132
|
-
▼ │
|
|
133
|
-
read orders.test (500 lines) │
|
|
134
|
-
│ ▼
|
|
135
|
-
▼ Done. Full picture.
|
|
136
|
-
grep "import.*processOrder" Ready to make the change.
|
|
137
|
-
│
|
|
138
|
-
▼
|
|
139
|
-
read routes.ts (300 lines)
|
|
140
|
-
│
|
|
141
|
-
▼
|
|
142
|
-
... still not sure about full impact
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
8+ tool calls 2 tool calls
|
|
146
|
-
Reads thousands of lines Reads zero full files
|
|
147
|
-
Context spent on file contents Context spent on reasoning
|
|
148
|
-
```
|
|
48
|
+
UCN uses tree-sitter to parse code into an AST, then builds a call graph and symbol table on top of it. Instead of matching text, it understands which functions call which, what depends on what, and what's unused. Everything runs locally.
|
|
149
49
|
|
|
150
|
-
|
|
50
|
+
"What happens when `build()` runs?"
|
|
151
51
|
|
|
152
52
|
```
|
|
153
|
-
|
|
154
|
-
────────────────────── ──────────────────────
|
|
155
|
-
|
|
156
|
-
git diff ucn diff_impact
|
|
157
|
-
│ │
|
|
158
|
-
▼ ▼
|
|
159
|
-
see changed lines, but which 13 modified functions
|
|
160
|
-
functions do they belong to? 8 new functions
|
|
161
|
-
│ 22 call sites across 9 files
|
|
162
|
-
▼ │
|
|
163
|
-
read each file to map hunks ▼
|
|
164
|
-
to function boundaries Each function shown with:
|
|
165
|
-
│ • which lines changed
|
|
166
|
-
▼ • every downstream caller
|
|
167
|
-
ucn impact on each function • caller context
|
|
168
|
-
you identified (repeat 5-10x) │
|
|
169
|
-
│ ▼
|
|
170
|
-
▼ Done. Full blast radius.
|
|
171
|
-
hope you didn't miss one One command.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
10+ tool calls 1 tool call
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
---
|
|
178
|
-
|
|
179
|
-
## Text search vs AST
|
|
53
|
+
$ ucn trace build --depth=2
|
|
180
54
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
199
|
-
│ ucn context "processOrder" │
|
|
200
|
-
│ │
|
|
201
|
-
│ Callers: │
|
|
202
|
-
│ handleCheckout src/api/checkout.ts:45 │
|
|
203
|
-
│ batchProcess src/workers/batch.ts:12 │
|
|
204
|
-
│ runDailyOrders src/jobs/daily.ts:88 │
|
|
205
|
-
│ │
|
|
206
|
-
│ Callees: │
|
|
207
|
-
│ validateItems src/orders/validate.ts:20 │
|
|
208
|
-
│ calculateTotal src/orders/pricing.ts:55 │
|
|
209
|
-
│ saveOrder src/db/orders.ts:30 │
|
|
210
|
-
│ │
|
|
211
|
-
│ 3 callers, 3 callees. Verified from the AST. │
|
|
212
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
55
|
+
build
|
|
56
|
+
├── detectProjectPattern (discovery.js:392) 1x
|
|
57
|
+
│ ├── checkDir (discovery.js:396) 2x
|
|
58
|
+
│ └── shouldIgnore (discovery.js:340) 1x
|
|
59
|
+
├── parseGitignore (discovery.js:123) 1x
|
|
60
|
+
├── expandGlob (discovery.js:183) 1x
|
|
61
|
+
│ ├── parseGlobPattern (discovery.js:219) 1x
|
|
62
|
+
│ ├── walkDir (discovery.js:276) 1x
|
|
63
|
+
│ └── compareNames (discovery.js:162) 1x
|
|
64
|
+
├── indexFile (project.js:236) 1x
|
|
65
|
+
│ ├── addSymbol (project.js:293) 4x
|
|
66
|
+
│ ├── detectLanguage (languages/index.js:157) 1x
|
|
67
|
+
│ ├── parseFile (parser.js:93) 1x
|
|
68
|
+
│ └── extractImports (imports.js:19) 1x
|
|
69
|
+
├── buildImportGraph (project.js:419) 1x
|
|
70
|
+
└── buildInheritanceGraph (project.js:465) 1x
|
|
213
71
|
```
|
|
214
72
|
|
|
215
|
-
|
|
73
|
+
One command. No files opened. The full execution flow with every function located by file and line.
|
|
216
74
|
|
|
217
75
|
---
|
|
218
76
|
|
|
219
|
-
##
|
|
220
|
-
|
|
221
|
-
Extract a function from a large file without reading it:
|
|
222
|
-
|
|
223
|
-
```
|
|
224
|
-
$ ucn fn expandGlob
|
|
225
|
-
|
|
226
|
-
core/discovery.js:135
|
|
227
|
-
[ 135- 166] expandGlob(pattern, options = {})
|
|
228
|
-
────────────────────────────────────────────────────────────
|
|
229
|
-
function expandGlob(pattern, options = {}) {
|
|
230
|
-
const root = path.resolve(options.root || process.cwd());
|
|
231
|
-
const ignores = options.ignores || DEFAULT_IGNORES;
|
|
232
|
-
...
|
|
233
|
-
return files.sort(compareNames);
|
|
234
|
-
}
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
See who calls it and what it calls:
|
|
77
|
+
## What it does
|
|
238
78
|
|
|
239
|
-
|
|
240
|
-
|
|
79
|
+
| Task | Command | Output |
|
|
80
|
+
|------|---------|--------|
|
|
81
|
+
| Understand one symbol deeply | `ucn about expandGlob` | Definition, callers, callees, tests |
|
|
82
|
+
| Who calls this and what do they pass? | `ucn impact shouldIgnore` | Call sites with argument context |
|
|
83
|
+
| Map an execution path | `ucn trace expandGlob --depth=2` | Call tree |
|
|
84
|
+
| Extract just one function | `ucn fn expandGlob` | Surgical snippet, no file read |
|
|
85
|
+
| Check all call sites match signature | `ucn verify expandGlob` | Mismatch/uncertain call sites |
|
|
86
|
+
| Review branch impact | `ucn diff-impact --base=main` | Changed functions + downstream callers |
|
|
87
|
+
| Find deletable code | `ucn deadcode` | Unused symbols, AST-verified |
|
|
88
|
+
| Get function + helpers inline | `ucn smart shouldIgnore` | Source with dependencies expanded |
|
|
241
89
|
|
|
242
|
-
|
|
243
|
-
════════════════════════════════════════════════════════════
|
|
244
|
-
|
|
245
|
-
CALLERS (7):
|
|
246
|
-
[1] cli/index.js:1847 [runGlobCommand]
|
|
247
|
-
const files = expandGlob(pattern);
|
|
248
|
-
[2] core/project.js:81
|
|
249
|
-
const files = expandGlob(pattern, {
|
|
250
|
-
[3] core/project.js:3434
|
|
251
|
-
const currentFiles = expandGlob(pattern, { root: this.root });
|
|
252
|
-
...
|
|
253
|
-
|
|
254
|
-
CALLEES (2):
|
|
255
|
-
[8] parseGlobPattern [utility] - core/discovery.js:171
|
|
256
|
-
[9] walkDir [utility] - core/discovery.js:227
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
See what breaks if you change it:
|
|
260
|
-
|
|
261
|
-
```
|
|
262
|
-
$ ucn impact shouldIgnore
|
|
263
|
-
|
|
264
|
-
Impact analysis for shouldIgnore
|
|
265
|
-
════════════════════════════════════════════════════════════
|
|
266
|
-
core/discovery.js:289
|
|
267
|
-
shouldIgnore (name, ignores, parentDir)
|
|
268
|
-
|
|
269
|
-
CALL SITES: 2
|
|
270
|
-
Files affected: 1
|
|
271
|
-
|
|
272
|
-
BY FILE:
|
|
273
|
-
|
|
274
|
-
core/discovery.js (2 calls)
|
|
275
|
-
:255 [walkDir]
|
|
276
|
-
if (shouldIgnore(entry.name, options.ignores, dir)) continue;
|
|
277
|
-
args: entry.name, options.ignores, dir
|
|
278
|
-
:373 [detectProjectPattern]
|
|
279
|
-
!shouldIgnore(entry.name, DEFAULT_IGNORES)) {
|
|
280
|
-
args: entry.name, DEFAULT_IGNORES
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
Get a function with all its dependencies inline:
|
|
284
|
-
|
|
285
|
-
```
|
|
286
|
-
$ ucn smart shouldIgnore
|
|
287
|
-
|
|
288
|
-
shouldIgnore (core/discovery.js:289)
|
|
289
|
-
════════════════════════════════════════════════════════════
|
|
290
|
-
function shouldIgnore(name, ignores, parentDir) {
|
|
291
|
-
for (const pattern of ignores) {
|
|
292
|
-
if (pattern.includes('*')) {
|
|
293
|
-
const regex = globToRegex(pattern);
|
|
294
|
-
...
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
...
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
─── DEPENDENCIES ───
|
|
301
|
-
|
|
302
|
-
// globToRegex [utility] (core/discovery.js:208)
|
|
303
|
-
function globToRegex(glob) {
|
|
304
|
-
let regex = glob.replace(/[.+^$[\]\\]/g, '\\$&');
|
|
305
|
-
...
|
|
306
|
-
return new RegExp('^' + regex + '$');
|
|
307
|
-
}
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
Trace the call tree:
|
|
311
|
-
|
|
312
|
-
```
|
|
313
|
-
$ ucn trace expandGlob --depth=2
|
|
314
|
-
|
|
315
|
-
Call tree for expandGlob
|
|
316
|
-
════════════════════════════════════════════════════════════
|
|
317
|
-
|
|
318
|
-
expandGlob
|
|
319
|
-
├── parseGlobPattern (core/discovery.js:171) [utility] 1x
|
|
320
|
-
│ └── globToRegex (core/discovery.js:208) [utility] 1x
|
|
321
|
-
└── walkDir (core/discovery.js:227) [utility] 1x
|
|
322
|
-
└── shouldIgnore (core/discovery.js:289) [utility] 1x
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
See the impact of your recent edits:
|
|
326
|
-
|
|
327
|
-
```
|
|
328
|
-
$ ucn diff-impact --base=HEAD~1
|
|
329
|
-
|
|
330
|
-
Diff Impact Analysis (vs HEAD~1)
|
|
331
|
-
════════════════════════════════════════════════════════════
|
|
332
|
-
3 modified, 1 new, 12 call sites across 4 files
|
|
333
|
-
|
|
334
|
-
MODIFIED FUNCTIONS:
|
|
335
|
-
|
|
336
|
-
processOrder
|
|
337
|
-
src/orders/service.ts:45
|
|
338
|
-
processOrder (items: Item[], user: User): Promise<Order>
|
|
339
|
-
Lines added: 48-52
|
|
340
|
-
Lines deleted: 49
|
|
341
|
-
Callers (3):
|
|
342
|
-
src/api/checkout.ts:89 [handleCheckout]
|
|
343
|
-
await processOrder(cart.items, req.user)
|
|
344
|
-
src/workers/batch.ts:12 [batchProcess]
|
|
345
|
-
processOrder(order.items, systemUser)
|
|
346
|
-
src/jobs/daily.ts:88 [runDailyOrders]
|
|
347
|
-
results.push(await processOrder(items, admin))
|
|
348
|
-
|
|
349
|
-
validateItems
|
|
350
|
-
src/orders/validate.ts:20
|
|
351
|
-
validateItems (items: Item[]): ValidationResult
|
|
352
|
-
Lines added: 25-30
|
|
353
|
-
Callers (2):
|
|
354
|
-
src/orders/service.ts:46 [processOrder]
|
|
355
|
-
const valid = validateItems(items)
|
|
356
|
-
src/api/admin.ts:55 [bulkValidate]
|
|
357
|
-
return items.map(i => validateItems([i]))
|
|
358
|
-
|
|
359
|
-
NEW FUNCTIONS:
|
|
360
|
-
calculateShipping — src/orders/shipping.ts:10
|
|
361
|
-
calculateShipping (items: Item[], region: Region): number
|
|
362
|
-
|
|
363
|
-
MODULE-LEVEL CHANGES:
|
|
364
|
-
src/orders/service.ts: +5 lines, -1 lines
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
Scoped to staged changes or a specific file:
|
|
368
|
-
|
|
369
|
-
```
|
|
370
|
-
$ ucn diff-impact --staged # Only what's staged for commit
|
|
371
|
-
$ ucn diff-impact --base=main # Everything since branching from main
|
|
372
|
-
$ ucn diff-impact --file=src/orders # Only changes in this path
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
Find unused code:
|
|
376
|
-
|
|
377
|
-
```
|
|
378
|
-
$ ucn deadcode
|
|
379
|
-
|
|
380
|
-
Dead code: 15 unused symbol(s)
|
|
90
|
+
---
|
|
381
91
|
|
|
382
|
-
|
|
383
|
-
[1649-1654] extractFunctionNameFromContent (function)
|
|
384
|
-
core/project.js
|
|
385
|
-
[1664-1694] findReExportsOf (method)
|
|
386
|
-
[1998-2020] withCompleteness (method)
|
|
387
|
-
...
|
|
388
|
-
```
|
|
92
|
+
## Setup
|
|
389
93
|
|
|
390
|
-
|
|
94
|
+
### CLI
|
|
391
95
|
|
|
392
|
-
|
|
96
|
+
Already installed above. A few more examples:
|
|
393
97
|
|
|
394
98
|
```bash
|
|
395
|
-
|
|
99
|
+
ucn fn handleRequest --file api # extract function from specific file
|
|
100
|
+
ucn toc # project overview
|
|
101
|
+
ucn --interactive # REPL mode, index stays in memory
|
|
396
102
|
```
|
|
397
103
|
|
|
398
|
-
###
|
|
104
|
+
### MCP Server (for AI agents)
|
|
399
105
|
|
|
400
|
-
One-line setup
|
|
106
|
+
One-line setup:
|
|
401
107
|
|
|
402
108
|
```bash
|
|
403
109
|
# Claude Code
|
|
@@ -410,7 +116,8 @@ codex mcp add ucn -- npx -y ucn --mcp
|
|
|
410
116
|
code --add-mcp '{"name":"ucn","command":"npx","args":["-y","ucn","--mcp"]}'
|
|
411
117
|
```
|
|
412
118
|
|
|
413
|
-
|
|
119
|
+
<details>
|
|
120
|
+
<summary>Or add to the MCP config file manually</summary>
|
|
414
121
|
|
|
415
122
|
```json
|
|
416
123
|
{
|
|
@@ -423,8 +130,7 @@ Or add to your client's MCP config file manually:
|
|
|
423
130
|
}
|
|
424
131
|
```
|
|
425
132
|
|
|
426
|
-
|
|
427
|
-
<summary>VS Code Copilot uses a slightly different format (.vscode/mcp.json)</summary>
|
|
133
|
+
VS Code uses `.vscode/mcp.json`:
|
|
428
134
|
|
|
429
135
|
```json
|
|
430
136
|
{
|
|
@@ -437,11 +143,14 @@ Or add to your client's MCP config file manually:
|
|
|
437
143
|
}
|
|
438
144
|
}
|
|
439
145
|
```
|
|
146
|
+
|
|
440
147
|
</details>
|
|
441
148
|
|
|
442
|
-
|
|
149
|
+
All 28 commands ship as a single MCP tool, under 2KB of schema in the agent's context.
|
|
150
|
+
|
|
151
|
+
### Agent Skill (no server needed)
|
|
443
152
|
|
|
444
|
-
|
|
153
|
+
Drop-in for Claude Code or Codex CLI:
|
|
445
154
|
|
|
446
155
|
```bash
|
|
447
156
|
# Claude Code
|
|
@@ -453,135 +162,155 @@ mkdir -p ~/.agents/skills
|
|
|
453
162
|
cp -r "$(npm root -g)/ucn/.claude/skills/ucn" ~/.agents/skills/
|
|
454
163
|
```
|
|
455
164
|
|
|
456
|
-
|
|
165
|
+
---
|
|
457
166
|
|
|
458
|
-
|
|
167
|
+
## Examples
|
|
168
|
+
|
|
169
|
+
**Extract a function** without reading the file:
|
|
459
170
|
|
|
460
|
-
```bash
|
|
461
|
-
ucn toc # Project overview
|
|
462
|
-
ucn about handleRequest # Understand a function
|
|
463
|
-
ucn impact handleRequest # Before modifying
|
|
464
|
-
ucn fn handleRequest --file api # Extract specific function
|
|
465
|
-
ucn --interactive # Multiple queries, index stays in memory
|
|
466
171
|
```
|
|
172
|
+
$ ucn fn expandGlob
|
|
467
173
|
|
|
468
|
-
|
|
174
|
+
core/discovery.js:183
|
|
175
|
+
[ 183- 214] expandGlob(pattern, options = {})
|
|
176
|
+
────────────────────────────────────────────────────────────
|
|
177
|
+
function expandGlob(pattern, options = {}) {
|
|
178
|
+
const root = path.resolve(options.root || process.cwd());
|
|
179
|
+
const ignores = options.ignores || DEFAULT_IGNORES;
|
|
180
|
+
...
|
|
181
|
+
return files.sort(compareNames);
|
|
182
|
+
}
|
|
183
|
+
```
|
|
469
184
|
|
|
470
|
-
|
|
185
|
+
**See callers and callees:**
|
|
471
186
|
|
|
472
|
-
Investigating a bug:
|
|
473
|
-
```bash
|
|
474
|
-
ucn about problematic_function # Understand it fully
|
|
475
|
-
ucn trace problematic_function --depth=2 # See what it calls
|
|
476
187
|
```
|
|
188
|
+
$ ucn context expandGlob
|
|
477
189
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
190
|
+
CALLERS (7):
|
|
191
|
+
[1] cli/index.js:785 [runGlobCommand]
|
|
192
|
+
const files = expandGlob(pattern);
|
|
193
|
+
[2] core/cache.js:149 [isCacheStale]
|
|
194
|
+
const currentFiles = expandGlob(pattern, globOpts);
|
|
195
|
+
[3] core/project.js:171 [build]
|
|
196
|
+
const files = expandGlob(pattern, globOpts);
|
|
197
|
+
...
|
|
198
|
+
|
|
199
|
+
CALLEES (3):
|
|
200
|
+
[8] parseGlobPattern [utility] - core/discovery.js:219
|
|
201
|
+
[9] walkDir [utility] - core/discovery.js:276
|
|
202
|
+
[10] compareNames [utility] - core/discovery.js:162
|
|
484
203
|
```
|
|
485
204
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
ucn diff-impact # What did I change + who calls it?
|
|
489
|
-
ucn diff-impact --base=main # Full branch impact vs main
|
|
490
|
-
ucn diff-impact --staged # Only staged changes
|
|
205
|
+
**See impact of recent edits:**
|
|
206
|
+
|
|
491
207
|
```
|
|
208
|
+
$ ucn diff-impact --base=HEAD~1
|
|
492
209
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
210
|
+
3 modified, 1 new, 12 call sites across 4 files
|
|
211
|
+
|
|
212
|
+
MODIFIED FUNCTIONS:
|
|
213
|
+
|
|
214
|
+
processOrder
|
|
215
|
+
src/orders/service.ts:45
|
|
216
|
+
Lines added: 48-52, Lines deleted: 49
|
|
217
|
+
Callers (3):
|
|
218
|
+
src/api/checkout.ts:89 [handleCheckout]
|
|
219
|
+
await processOrder(cart.items, req.user)
|
|
220
|
+
src/workers/batch.ts:12 [batchProcess]
|
|
221
|
+
processOrder(order.items, systemUser)
|
|
222
|
+
src/jobs/daily.ts:88 [runDailyOrders]
|
|
223
|
+
results.push(await processOrder(items, admin))
|
|
497
224
|
```
|
|
498
225
|
|
|
499
|
-
|
|
226
|
+
**Trace a call tree:**
|
|
500
227
|
|
|
501
|
-
|
|
228
|
+
```
|
|
229
|
+
$ ucn trace expandGlob --depth=2
|
|
230
|
+
|
|
231
|
+
expandGlob
|
|
232
|
+
├── parseGlobPattern (core/discovery.js:219) [utility] 1x
|
|
233
|
+
│ └── globToRegex (core/discovery.js:256) [utility] 1x
|
|
234
|
+
├── walkDir (core/discovery.js:276) [utility] 1x
|
|
235
|
+
│ ├── compareNames (core/discovery.js:162) [utility] 1x
|
|
236
|
+
│ ├── shouldIgnore (core/discovery.js:340) [utility] 1x
|
|
237
|
+
│ └── walkDir (core/discovery.js:276) [utility] 1x (see above)
|
|
238
|
+
└── compareNames (core/discovery.js:162) [utility] 1x (see above)
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Find unused code:**
|
|
502
242
|
|
|
503
243
|
```
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
│ │ the rest. UCN complements, doesn't │
|
|
511
|
-
│ │ replace. │
|
|
512
|
-
│ │ │
|
|
513
|
-
├──────────────────────────┼──────────────────────────────────────────┤
|
|
514
|
-
│ │ │
|
|
515
|
-
│ Dynamic dispatch │ getattr(), reflection, eval() — UCN │
|
|
516
|
-
│ │ does static analysis and can't follow │
|
|
517
|
-
│ │ calls that only exist at runtime. │
|
|
518
|
-
│ │ │
|
|
519
|
-
├──────────────────────────┼──────────────────────────────────────────┤
|
|
520
|
-
│ │ │
|
|
521
|
-
│ Duck-typed methods │ obj.method() in JS/TS/Python — when │
|
|
522
|
-
│ │ the receiver type is ambiguous, results │
|
|
523
|
-
│ │ are marked "uncertain" so the agent │
|
|
524
|
-
│ │ knows to verify. Go/Rust/Java resolve │
|
|
525
|
-
│ │ with high confidence. │
|
|
526
|
-
│ │ │
|
|
527
|
-
├──────────────────────────┼──────────────────────────────────────────┤
|
|
528
|
-
│ │ │
|
|
529
|
-
│ Single project scope │ UCN follows imports within the project │
|
|
530
|
-
│ │ but stops at the boundary — no tracing │
|
|
531
|
-
│ │ into node_modules or site-packages. │
|
|
532
|
-
│ │ │
|
|
533
|
-
├──────────────────────────┼──────────────────────────────────────────┤
|
|
534
|
-
│ │ │
|
|
535
|
-
│ First-query index time │ Tree-sitter index is built on first │
|
|
536
|
-
│ │ query. A few seconds on large projects. │
|
|
537
|
-
│ │ Cached and incrementally updated — │
|
|
538
|
-
│ │ only changed files are re-indexed. │
|
|
539
|
-
│ │ │
|
|
540
|
-
└──────────────────────────┴──────────────────────────────────────────┘
|
|
244
|
+
$ ucn deadcode --exclude=test
|
|
245
|
+
|
|
246
|
+
Dead code: 1 unused symbol(s)
|
|
247
|
+
|
|
248
|
+
core/discovery.js
|
|
249
|
+
[ 162- 166] legacyResolve (function)
|
|
541
250
|
```
|
|
542
251
|
|
|
543
252
|
---
|
|
544
253
|
|
|
545
|
-
##
|
|
254
|
+
## Workflows
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
# Investigating a bug
|
|
258
|
+
ucn about buggyFunction # understand it fully
|
|
259
|
+
ucn trace buggyFunction --depth=2 # see what it calls
|
|
260
|
+
|
|
261
|
+
# Before modifying code
|
|
262
|
+
ucn impact theFunction # who will break?
|
|
263
|
+
ucn smart theFunction # function + its helpers inline
|
|
264
|
+
# ... make changes ...
|
|
265
|
+
ucn verify theFunction # do all call sites still match?
|
|
266
|
+
|
|
267
|
+
# Before committing
|
|
268
|
+
ucn diff-impact --staged # what I changed + who calls it
|
|
269
|
+
|
|
270
|
+
# Cleanup
|
|
271
|
+
ucn deadcode --exclude=test # what can be deleted?
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
---
|
|
546
275
|
|
|
547
|
-
All commands
|
|
276
|
+
## All 28 commands
|
|
548
277
|
|
|
549
278
|
```
|
|
550
279
|
UNDERSTAND MODIFY SAFELY
|
|
551
280
|
───────────────────── ─────────────────────
|
|
552
|
-
about
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
(quick overview)
|
|
559
|
-
verify check all sites
|
|
560
|
-
smart function + helpers match signature
|
|
561
|
-
expanded inline
|
|
562
|
-
plan preview a refactor
|
|
563
|
-
trace call tree — map before doing it
|
|
564
|
-
a whole pipeline
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
FIND & NAVIGATE ARCHITECTURE
|
|
281
|
+
about full picture impact all call sites
|
|
282
|
+
context callers + callees diff-impact git diff + callers
|
|
283
|
+
smart function + helpers verify signature check
|
|
284
|
+
trace call tree plan refactor preview
|
|
285
|
+
|
|
286
|
+
FIND & EXTRACT ARCHITECTURE
|
|
568
287
|
───────────────────── ─────────────────────
|
|
569
288
|
find locate definitions imports file dependencies
|
|
570
|
-
usages all occurrences exporters
|
|
571
|
-
fn extract
|
|
572
|
-
class extract
|
|
573
|
-
toc project overview tests find
|
|
574
|
-
deadcode unused
|
|
289
|
+
usages all occurrences exporters reverse dependencies
|
|
290
|
+
fn extract function graph dependency tree
|
|
291
|
+
class extract class related sibling functions
|
|
292
|
+
toc project overview tests find test coverage
|
|
293
|
+
deadcode unused code stacktrace error trace context
|
|
575
294
|
search text search api public API surface
|
|
576
295
|
example best usage example typedef type definitions
|
|
577
|
-
lines extract line range
|
|
578
|
-
expand drill into context stats project
|
|
296
|
+
lines extract line range file-exports file's exports
|
|
297
|
+
expand drill into context stats project stats
|
|
579
298
|
```
|
|
580
299
|
|
|
581
300
|
---
|
|
582
301
|
|
|
302
|
+
## Limitations
|
|
303
|
+
|
|
304
|
+
UCN is static AST analysis, not runtime instrumentation.
|
|
305
|
+
|
|
306
|
+
- **5 languages + HTML** — JS/TS, Python, Go, Rust, Java. Falls back to text search for others.
|
|
307
|
+
- **Static analysis only** — Can't follow `eval()`, `getattr()`, reflection, or other dynamic dispatch.
|
|
308
|
+
- **Duck-typed methods** — `obj.method()` in JS/TS/Python is marked "uncertain" when the receiver type is ambiguous. Go/Rust/Java resolve with high confidence.
|
|
309
|
+
- **Single project scope** — Follows imports within the project but not into `node_modules` or `site-packages`.
|
|
310
|
+
- **First-query index time** — A few seconds on large projects. Cached incrementally after that.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
583
314
|
## License
|
|
584
315
|
|
|
585
316
|
MIT
|
|
586
|
-
|
|
587
|
-
UCN - Universal Code Navigator
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ucn",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.26",
|
|
4
4
|
"mcpName": "io.github.mleoca/ucn",
|
|
5
5
|
"description": "Universal Code Navigator — AST-based call graph analysis for AI agents. Find callers, trace impact, detect dead code across JS/TS, Python, Go, Rust, Java, and HTML. CLI, MCP server, and agent skill.",
|
|
6
6
|
"main": "index.js",
|