ucn 3.8.23 → 3.8.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/.claude/skills/ucn/SKILL.md +127 -12
- package/README.md +152 -156
- package/cli/index.js +363 -37
- package/core/analysis.js +936 -32
- package/core/bridge.js +1095 -0
- package/core/brief.js +408 -0
- package/core/cache.js +105 -5
- package/core/callers.js +72 -18
- package/core/check.js +200 -0
- package/core/discovery.js +57 -34
- package/core/entrypoints.js +638 -4
- package/core/execute.js +304 -5
- package/core/git-enrich.js +130 -0
- package/core/graph.js +24 -2
- package/core/output/analysis.js +157 -25
- package/core/output/brief.js +100 -0
- package/core/output/check.js +79 -0
- package/core/output/doctor.js +85 -0
- package/core/output/endpoints.js +239 -0
- package/core/output/extraction.js +2 -0
- package/core/output/find.js +126 -39
- package/core/output/graph.js +48 -15
- package/core/output/refactoring.js +103 -5
- package/core/output/reporting.js +63 -23
- package/core/output/search.js +110 -17
- package/core/output/shared.js +56 -2
- package/core/output.js +4 -0
- package/core/parser.js +8 -2
- package/core/project.js +39 -3
- package/core/registry.js +30 -14
- package/core/reporting.js +465 -2
- package/core/search.js +130 -52
- package/core/shared.js +101 -5
- package/core/tracing.js +16 -6
- package/core/verify.js +982 -95
- package/languages/go.js +91 -6
- package/languages/html.js +10 -0
- package/languages/java.js +151 -35
- package/languages/javascript.js +290 -33
- package/languages/python.js +78 -11
- package/languages/rust.js +267 -12
- package/languages/utils.js +315 -3
- package/mcp/server.js +91 -16
- package/package.json +9 -1
|
@@ -71,6 +71,8 @@ ucn trace generate_report --all # all children at default depth
|
|
|
71
71
|
|
|
72
72
|
Shows the entire pipeline — what `generate_report` calls, what those functions call, etc. — as an indented tree. No file reading needed. Invaluable for understanding orchestrator functions or entry points.
|
|
73
73
|
|
|
74
|
+
**Prefer `trace` over chained `about` calls.** If you find yourself running `ucn about` 4–5 times in a row to follow a call chain (entry → leaves), one `ucn trace <fn> --depth=N` returns the same information in a single call. Use `--depth=N` to limit how deep the tree goes.
|
|
75
|
+
|
|
74
76
|
### 5. `fn` / `class` — Extract without reading the whole file
|
|
75
77
|
|
|
76
78
|
Pull one or more functions out of a large file. Supports comma-separated names for bulk extraction.
|
|
@@ -91,15 +93,56 @@ ucn deadcode --exclude=test # Skip test files (most useful)
|
|
|
91
93
|
ucn deadcode --include-decorated # Include framework-registered functions
|
|
92
94
|
```
|
|
93
95
|
|
|
94
|
-
### 7. `
|
|
96
|
+
### 7. `brief` — One-screen "before-I-touch-this" summary
|
|
97
|
+
|
|
98
|
+
AST-only summary of a function: typed signature, first sentence of docstring,
|
|
99
|
+
side-effect classification (fs/network/process/global_mutation), and complexity
|
|
100
|
+
metrics (branches, depth, line count). Lighter than `about`, more useful than
|
|
101
|
+
`fn` when you don't need the body.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
ucn brief fetch_user
|
|
105
|
+
# fetch_user(user_id: int): dict
|
|
106
|
+
# svc.py:4-8 (5 lines)
|
|
107
|
+
# "Fetch a user from the API."
|
|
108
|
+
# async: no | side_effects: [fs, network, process] | complexity: branches=2, depth=2
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 8. `doctor` — Project trust report
|
|
112
|
+
|
|
113
|
+
One command that tells you how much UCN trusts the index for this project:
|
|
114
|
+
file/symbol counts, language breakdown, dynamic-import / eval / reflection
|
|
115
|
+
blind spots, parse failures, and a verdict (HIGH/MEDIUM/LOW). Add `--deep` to
|
|
116
|
+
sample resolution coverage and bucket edges by confidence.
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
ucn doctor # fast: counts + blind spots + verdict
|
|
120
|
+
ucn doctor --deep # also samples resolution coverage
|
|
121
|
+
ucn doctor --in=src/core # scope to a subtree
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 9. `check` — Pre-commit summary
|
|
125
|
+
|
|
126
|
+
Composes `diff-impact` + `verify` + `affected-tests` into one output. Lists
|
|
127
|
+
changed/added/deleted functions, flags signature drift across call sites,
|
|
128
|
+
calls out new functions with no callers, and recommends which tests to run.
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
ucn check # vs HEAD
|
|
132
|
+
ucn check --base=main # vs main branch
|
|
133
|
+
ucn check --staged # only staged changes
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 10. `entrypoints` — Detect framework entry points
|
|
95
137
|
|
|
96
138
|
Lists functions registered as framework handlers (HTTP routes, DI beans, job schedulers, etc.). Detects patterns across Express, FastAPI, Flask, Spring, Gin, Actix, Celery, pytest, and more.
|
|
97
139
|
|
|
98
140
|
```bash
|
|
99
|
-
ucn entrypoints # All detected entry points
|
|
141
|
+
ucn entrypoints # All detected entry points (tests included by default)
|
|
100
142
|
ucn entrypoints --type=http # HTTP routes only
|
|
101
143
|
ucn entrypoints --framework=express # Specific framework
|
|
102
144
|
ucn entrypoints --file=routes/ # Scoped to files
|
|
145
|
+
ucn entrypoints --exclude-tests # Hide test fixtures (JUnit @Test, pytest, Rust #[test], etc.)
|
|
103
146
|
```
|
|
104
147
|
|
|
105
148
|
## When to Use the Other Commands
|
|
@@ -117,10 +160,10 @@ ucn entrypoints --file=routes/ # Scoped to files
|
|
|
117
160
|
| Understanding who depends on a file | `ucn exporters <file>` | Which files import it |
|
|
118
161
|
| See what a file exports | `ucn file-exports <file>` | All exported functions, classes, variables with signatures |
|
|
119
162
|
| Quick project overview | `ucn toc` | Every file with function/class counts and line counts |
|
|
120
|
-
| Project complexity stats | `ucn stats` | File counts, symbol counts, lines by language. `--functions` for per-function line counts |
|
|
163
|
+
| Project complexity stats | `ucn stats` | File counts, symbol counts, lines by language. `--functions` for per-function line counts. `--hot --top=N` for the most-called functions (orientation primitive on a new repo) |
|
|
121
164
|
| Find by glob pattern | `ucn find "handle*"` | Locate definitions matching a glob (supports * and ?) |
|
|
122
165
|
| Text search with context | `ucn search term --context=3` | Like grep -C 3, shows surrounding lines |
|
|
123
|
-
| Regex search (default) | `ucn search '\d+'` |
|
|
166
|
+
| Regex search (default) | `ucn search '\d+'` | JavaScript regex (V8 engine). See "Regex notes" below for syntax — alternation is `a|b`, not grep-style |
|
|
124
167
|
| Text search filtered | `ucn search term --exclude=test` | Search only in matching files |
|
|
125
168
|
| Structural search (index) | `ucn search --type=function --param=Request` | Query the symbol table, not text. Finds functions by param, return type, decorator, etc. |
|
|
126
169
|
| Find all db.* calls | `ucn search --type=call --receiver=db` | Search call sites by receiver — something grep can't do |
|
|
@@ -133,13 +176,72 @@ ucn entrypoints --file=routes/ # Scoped to files
|
|
|
133
176
|
| File-level dependency tree | `ucn graph <file> --depth=1` | Visual import tree. Setting `--depth=N` expands all children. Can be noisy — use depth=1 for large projects. For function-level flow, use `trace` instead |
|
|
134
177
|
| Are there circular dependencies? | `ucn circular-deps` | Detect circular import chains. `--file=<pattern>` filters to cycles involving a file. `--exclude=test` skips test files |
|
|
135
178
|
| What are the framework entry points? | `ucn entrypoints` | Lists all detected routes, DI beans, tasks, etc. Filter: `--type=http`, `--framework=express` |
|
|
179
|
+
| Polyglot route ↔ request matching | `ucn endpoints --bridge` | Server routes (Express/Fastify/Koa/NestJS/Flask/FastAPI/Spring/JAX-RS/Gin/Echo/Chi/Fiber/axum/actix/Next.js) ↔ client requests (fetch/axios/requests/httpx/RestTemplate/WebClient/reqwest). Match confidence: EXACT, PARTIAL, UNCERTAIN. Filter with `--method`, `--prefix`, `--server-only`, `--client-only`, `--unmatched`, `--hide-uncertain` |
|
|
136
180
|
| Find which tests cover a function | `ucn tests <name>` | Test files and test function names. Scope with `--file`, `--class-name`, `--exclude`, `--calls-only` |
|
|
137
|
-
| Extract specific lines from a file | `ucn lines --file=<file
|
|
181
|
+
| Extract specific lines from a file | `ucn lines 10-20 --file=<file>` | Pull a line range without reading the whole file |
|
|
138
182
|
| Find type definitions | `ucn typedef <name>` | Interfaces, enums, structs, traits, type aliases |
|
|
139
183
|
| See a project's public API | `ucn api` or `ucn api --file=<file>` | All exported/public symbols with signatures |
|
|
140
184
|
| Drill into context results | `ucn expand <N>` | Show source code for item N from a previous `context` call |
|
|
141
185
|
| Best usage example of a function | `ucn example <name>` | Finds and scores the best call site with surrounding context |
|
|
142
186
|
| Debug a stack trace | `ucn stacktrace --stack="<trace>"` | Parses stack frames and shows source context per frame |
|
|
187
|
+
| Quick look before touching a function | `ucn brief <name>` | Signature + docstring + side effects + complexity, one screen |
|
|
188
|
+
| Project trust report | `ucn doctor [--deep]` | Index coverage, blind spots, parse failures, verdict |
|
|
189
|
+
| Pre-commit summary | `ucn check [--base=main]` | Changed funcs + signature drift + affected tests in one shot |
|
|
190
|
+
| Find missing-await bugs | `ucn audit-async` | Lists async calls inside async functions that lack `await`. JS/TS/Python only. Filter with `--file`, `--exclude`, `--limit` |
|
|
191
|
+
|
|
192
|
+
## Regex Notes (`search` command)
|
|
193
|
+
|
|
194
|
+
`search` uses **JavaScript regex** (the V8 engine), not grep BRE/ERE. Common gotchas:
|
|
195
|
+
|
|
196
|
+
- Alternation is `a|b`, **not** `a\|b`. `ucn search "flask|fastapi|django"` works; `ucn search "flask\|fastapi\|django"` matches the literal string.
|
|
197
|
+
- `(`, `[`, `{` outside character classes do **not** need escaping for literal match in most cases — but normal JS regex semantics apply (you can still escape them for clarity).
|
|
198
|
+
- Wrap the pattern in single quotes so the shell does not interpret special characters (`*`, `?`, `\`, `$`, etc.).
|
|
199
|
+
- Default is case-insensitive; pass `--case-sensitive` to flip.
|
|
200
|
+
- `--no-regex` forces literal-string search if you need to match regex metacharacters as text without escaping.
|
|
201
|
+
|
|
202
|
+
## Reading Call-Site Patterns
|
|
203
|
+
|
|
204
|
+
`verify`, `impact`, and `about` annotate call sites with structural classification flags. Watch for these in summary lines (`Patterns: 4 in try, 4 in callback`) and per-call-site entries:
|
|
205
|
+
|
|
206
|
+
| Flag | What it means | Why it matters |
|
|
207
|
+
|------|--------------|---------------|
|
|
208
|
+
| `inLoop` | Call is inside a `for`/`while`/comprehension | N+1 query risk, repeated work, performance hot path |
|
|
209
|
+
| `inTry` | Call is wrapped in try/catch (or equivalent) | Errors are handled — different from "must fix" code paths |
|
|
210
|
+
| `inCallback` | Call sits inside a callback/lambda/closure that's not the enclosing function | Async deferred work, may run on a different stack frame |
|
|
211
|
+
| `inTestCase` | Call originates from inside a test function | Isolate production callers from test setup |
|
|
212
|
+
| `awaited` | Call's parent is `await` / `Promise.then` (JS/TS/Python) | Confirms async coordination — its absence on async callees signals a missing-await bug |
|
|
213
|
+
|
|
214
|
+
`audit-async` is the focused tool for the `awaited=false` case across an entire async function body.
|
|
215
|
+
|
|
216
|
+
## Confidence Scores
|
|
217
|
+
|
|
218
|
+
`about` and `context` show confidence per caller/callee edge by default (e.g. `confidence: 0.65 (scope-match)`). Resolution labels (high to low):
|
|
219
|
+
|
|
220
|
+
| Label | Score | Meaning |
|
|
221
|
+
|-------|-------|---------|
|
|
222
|
+
| `exact-binding` | 0.98 | Import or binding evidence — direct call |
|
|
223
|
+
| `same-class` | 0.92 | Method call resolved within the enclosing class |
|
|
224
|
+
| `receiver-hint` | 0.80 | Receiver type inferred (Go/Java/Rust) — e.g. `f.run()` where `f: Filter` |
|
|
225
|
+
| `scope-match` | 0.65 | Symbol resolved by name within a file/package scope |
|
|
226
|
+
| `name-only` | 0.40 | Name match only, no binding/scope evidence — review before trusting |
|
|
227
|
+
| `uncertain` | 0.25 | Ambiguous — multiple candidates, hidden unless `--include-uncertain` |
|
|
228
|
+
|
|
229
|
+
Filter or hide:
|
|
230
|
+
- `--min-confidence=0.7` — keep only high-confidence edges (≥ same-class)
|
|
231
|
+
- `--hide-confidence` — silence the scores (legacy `--no-confidence` is a silent alias)
|
|
232
|
+
- `--include-uncertain` — include otherwise-filtered low-confidence matches
|
|
233
|
+
|
|
234
|
+
## Symbol Handles (stable IDs)
|
|
235
|
+
|
|
236
|
+
Every result that lists a symbol emits a **handle** in the form `relativePath:line:name` (e.g. `core/api.ts:42:handler`). Pass it back to any name-accepting command and resolution is pinned to that exact definition — no name disambiguation, no `--file` needed.
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
ucn find handler # → emits src/api.ts:42:handler
|
|
240
|
+
ucn brief src/api.ts:42:handler # pins to that exact one
|
|
241
|
+
ucn impact src/api.ts:42:handler # same
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
The shorter `relativePath:line` form (no `:name`) also works — UCN looks up the symbol by location. Plain names (`handler`) still work for the fuzzy/heuristic path.
|
|
143
245
|
|
|
144
246
|
## Command Format
|
|
145
247
|
|
|
@@ -157,14 +259,15 @@ ucn [target] <command> [name] [--flags]
|
|
|
157
259
|
|
|
158
260
|
| Flag | When to use it |
|
|
159
261
|
|------|---------------|
|
|
160
|
-
| `--class-name=X` | Scope to specific class (e.g., `--class-name=Repository` for method `save`). Works with `
|
|
262
|
+
| `--class-name=X` | Scope to specific class (e.g., `--class-name=Repository` for method `save`). Works with `about`, `context`, `impact`, `blast`, `smart`, `trace`, `reverse-trace`, `example`, `related`, `brief`, `find`, `usages`, `tests`, `affected-tests`, `fn`, `verify`, `plan`, `typedef` |
|
|
161
263
|
| `--file=<pattern>` | Disambiguate when a name exists in multiple files (e.g., `--file=api`) |
|
|
162
264
|
| `--exclude=test,mock` | Focus on production code only |
|
|
163
265
|
| `--in=src/core` | Limit search to a subdirectory |
|
|
164
266
|
| `--depth=N` | Control tree depth for `trace`, `graph`, and detail level for `find` (default 3). Also expands all children — no breadth limit |
|
|
165
|
-
| `--all` | Expand truncated sections
|
|
267
|
+
| `--all` | Expand truncated sections. Applies to `about`, `blast`, `trace`, `reverse-trace`, `related`, `find`, `toc`, `fn`, `class`, `graph`, `diff-impact` |
|
|
166
268
|
| `--include-tests` | Include test files in usage counts (`about`) and results (`find`, `usages`, `deadcode`). Callers always include tests. |
|
|
167
|
-
| `--
|
|
269
|
+
| `--exclude-tests` | Exclude test entries from `entrypoints` (tests are included by default since they ARE entry points). |
|
|
270
|
+
| `--include-methods` | Include `obj.method()` calls in caller/callee analysis. `impact` defaults to true (show all callable sites); other commands default to false (use `--no-include-methods` to opt out). Applies to `about`, `context`, `impact`, `verify`, `blast`, `smart`, `trace`, `reverse-trace`, `affected-tests` |
|
|
168
271
|
| `--base=<ref>` | Git ref for diff-impact (default: HEAD) |
|
|
169
272
|
| `--staged` | Analyze staged changes (diff-impact) |
|
|
170
273
|
| `--no-cache` | Force re-index after editing files |
|
|
@@ -172,19 +275,22 @@ ucn [target] <command> [name] [--flags]
|
|
|
172
275
|
| `--context=N` | Lines of surrounding context in `usages`/`search` output |
|
|
173
276
|
| `--no-regex` | Force plain text search (regex is default) |
|
|
174
277
|
| `--functions` | Show per-function line counts in `stats` (complexity audit) |
|
|
175
|
-
| `--
|
|
278
|
+
| `--hot` | List top N most-called functions in `stats` (use with `--top=N`, default 10). Best orientation primitive when entering a new repo |
|
|
279
|
+
| `--diverse` | Cluster `example` call sites by argument shape and return one representative per cluster (use with `--top=N`, default 3) |
|
|
280
|
+
| `--git` | Attach git enrichment to `about` / `brief`: last commit (ISO + author) and recent change count (last 30 days). Skipped silently when not a git repo |
|
|
281
|
+
| `--json` | Machine-readable JSON output. Some commands wrap in `{meta, data}` (e.g., `find`, `deadcode`); others return flat objects (e.g., `about`, `impact`, `verify`, `plan`, `imports`) — check each command's output shape |
|
|
176
282
|
| `--code-only` | Exclude matches in comments and strings (`search`/`usages`) |
|
|
177
283
|
| `--with-types` | Include related type definitions in `smart`/`about` output |
|
|
178
284
|
| `--detailed` | Show full symbol listing per file in `toc` |
|
|
179
285
|
| `--top-level` | Show only top-level functions in `toc` (exclude nested/indented) |
|
|
180
286
|
| `--top=N` | Limit result count (default: 10 for most commands) |
|
|
181
|
-
| `--limit=N` | Limit result count for `find`, `usages`, `
|
|
287
|
+
| `--limit=N` | Limit result count for `find`, `usages`, `toc`, `search`, `deadcode`, `entrypoints`, `endpoints`, `diff-impact`, `check`, `api`, `doctor`, `audit-async` |
|
|
182
288
|
| `--max-files=N` | Max files to index (for large projects with 10K+ files) |
|
|
183
289
|
| `--max-lines=N` | Max source lines for `class` (large classes show summary by default) |
|
|
184
290
|
| `--case-sensitive` | Case-sensitive text search (default: case-insensitive) |
|
|
185
291
|
| `--exact` | Exact name match only in `find`/`typedef` (no substring) |
|
|
186
|
-
| `--include-uncertain` | Include ambiguous/uncertain matches
|
|
187
|
-
| `--
|
|
292
|
+
| `--include-uncertain` | Include ambiguous/uncertain matches. Applies to `about`, `context`, `blast`, `smart`, `trace`, `reverse-trace`, `affected-tests` |
|
|
293
|
+
| `--hide-confidence` | Hide confidence scores (shown by default) in `context`/`about` |
|
|
188
294
|
| `--min-confidence=N` | Filter edges below confidence threshold (e.g., `--min-confidence=0.7` keeps only high-confidence edges) |
|
|
189
295
|
| `--calls-only` | Only show call/test-case matches in `tests` (skip file-level results) |
|
|
190
296
|
| `--add-param=<name>` | Add a parameter (`plan` command). Combine with `--default=<value>` |
|
|
@@ -193,6 +299,13 @@ ucn [target] <command> [name] [--flags]
|
|
|
193
299
|
| `--include-exported` | Include exported symbols in `deadcode` results |
|
|
194
300
|
| `--include-decorated` | Include decorated/annotated symbols in `deadcode` results |
|
|
195
301
|
| `--framework=X` | Filter `entrypoints` by framework (e.g., `express`, `spring`, `celery`) |
|
|
302
|
+
| `--bridge` | Match server routes to client requests (`endpoints`). Confidence tiers: EXACT, PARTIAL, UNCERTAIN |
|
|
303
|
+
| `--server-only` | Only list server routes (`endpoints`) |
|
|
304
|
+
| `--client-only` | Only list client requests (`endpoints`) |
|
|
305
|
+
| `--unmatched` | Only show routes/requests with no match (`endpoints`, pair with `--bridge`) |
|
|
306
|
+
| `--method=GET` | Filter by HTTP method (`endpoints`) |
|
|
307
|
+
| `--prefix=/api` | Filter routes/requests by path prefix (`endpoints`) |
|
|
308
|
+
| `--hide-uncertain` | Hide UNCERTAIN-confidence bridges (`endpoints`) |
|
|
196
309
|
| `--type=<kind>` | Structural search: `function`, `class`, `call`, `method`, `type`. Triggers index query instead of text grep |
|
|
197
310
|
| `--param=<name>` | Structural search: filter by parameter name or type (e.g., `--param=Request`) |
|
|
198
311
|
| `--receiver=<name>` | Structural search: filter calls by receiver (e.g., `--receiver=db` for all db.* calls) |
|
|
@@ -202,6 +315,8 @@ ucn [target] <command> [name] [--flags]
|
|
|
202
315
|
| `--unused` | Structural search: only symbols with zero callers |
|
|
203
316
|
| `--no-follow-symlinks` | Don't follow symbolic links during file discovery |
|
|
204
317
|
| `--workers=N` | Parallel build workers (auto-detect by default; `0` to disable; env: `UCN_WORKERS`) |
|
|
318
|
+
| `--deep` | `doctor` only: sample resolution coverage. Slower but produces confidence histogram. |
|
|
319
|
+
| `--compact` | One-line-per-item output for `about`/`context`/`find`/`usages`/`impact`. Halves token cost; same info. |
|
|
205
320
|
|
|
206
321
|
## Workflow Integration
|
|
207
322
|
|
package/README.md
CHANGED
|
@@ -51,21 +51,21 @@ ucn deadcode --exclude=test # unused code, AST-verified
|
|
|
51
51
|
$ ucn trace build --depth=2
|
|
52
52
|
|
|
53
53
|
build
|
|
54
|
-
├── detectProjectPattern (core/discovery.js:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
├──
|
|
58
|
-
├──
|
|
59
|
-
│
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
├──
|
|
63
|
-
│ ├──
|
|
64
|
-
│ ├── detectLanguage (languages/index.js:157) 1x
|
|
54
|
+
├── detectProjectPattern (core/discovery.js:431) 1x
|
|
55
|
+
├── parseGitignore (core/discovery.js:131) 1x
|
|
56
|
+
├── expandGlob (core/discovery.js:191) 1x
|
|
57
|
+
│ ├── parseGlobPattern (core/discovery.js:227) 1x
|
|
58
|
+
│ ├── walkDir (core/discovery.js:284) 1x
|
|
59
|
+
│ └── compareNames (core/discovery.js:170) 1x
|
|
60
|
+
├── parallelBuild (core/parallel-build.js:25) 1x
|
|
61
|
+
├── indexFile (core/project.js:310) 1x
|
|
62
|
+
│ ├── addSymbol (core/project.js:398) 4x
|
|
63
|
+
│ ├── detectLanguage (languages/index.js:209) 1x
|
|
65
64
|
│ ├── parse (core/parser.js:69) 1x
|
|
66
|
-
│
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
│ ├── extractImports (core/imports.js:19) 1x
|
|
66
|
+
│ └── extractExports (core/imports.js:44) 1x
|
|
67
|
+
├── buildImportGraph (core/project.js:631) 1x
|
|
68
|
+
└── buildInheritanceGraph (core/project.js:636) 1x
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
One command. No files opened. Every function located by file and line.
|
|
@@ -81,26 +81,28 @@ $ ucn about expandGlob
|
|
|
81
81
|
|
|
82
82
|
expandGlob (function)
|
|
83
83
|
════════════════════════════════════════════════════════════
|
|
84
|
-
core/discovery.js:
|
|
85
|
-
expandGlob (pattern, options = {})
|
|
84
|
+
core/discovery.js:191-222 → core/discovery.js:191:expandGlob
|
|
85
|
+
expandGlob (pattern: string, options: number = {}) : string[]
|
|
86
86
|
|
|
87
|
-
CALLERS (
|
|
88
|
-
|
|
87
|
+
CALLERS (7):
|
|
88
|
+
confidence: 0 high (>0.8), 7 medium (0.5-0.8), 0 low (<0.5)
|
|
89
|
+
cli/index.js:1190 [runGlobCommand]
|
|
89
90
|
const files = expandGlob(pattern);
|
|
90
|
-
|
|
91
|
+
confidence: 0.65 (scope-match)
|
|
92
|
+
core/cache.js:417 [isCacheStale]
|
|
91
93
|
const currentFiles = expandGlob(pattern, globOpts);
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
confidence: 0.65 (scope-match)
|
|
95
|
+
... (5 more)
|
|
94
96
|
|
|
95
97
|
CALLEES (3):
|
|
96
|
-
parseGlobPattern [utility] - core/discovery.js:
|
|
97
|
-
walkDir [utility] - core/discovery.js:
|
|
98
|
-
compareNames [utility] - core/discovery.js:
|
|
98
|
+
parseGlobPattern [utility] - core/discovery.js:227
|
|
99
|
+
walkDir [utility] {fs} - core/discovery.js:284
|
|
100
|
+
compareNames [utility] - core/discovery.js:170
|
|
99
101
|
|
|
100
|
-
TESTS:
|
|
102
|
+
TESTS: 5 matches in 1 file(s)
|
|
101
103
|
```
|
|
102
104
|
|
|
103
|
-
Need to trace execution upward instead? `ucn reverse-trace fn` walks the caller chain back to entry points.
|
|
105
|
+
Each caller comes with a confidence score (`exact-binding`, `same-class`, `receiver-hint`, `scope-match`, `name-only`) so you can tell direct calls from name-only matches. Add `--hide-confidence` to silence the scores, or `--min-confidence=0.7` to drop everything below `same-class`. Add `--git` to see who last touched the function. Need to trace execution upward instead? `ucn reverse-trace fn` walks the caller chain back to entry points.
|
|
104
106
|
|
|
105
107
|
## Change code without breaking things
|
|
106
108
|
|
|
@@ -109,38 +111,100 @@ Before touching a function, check if all existing call sites match its signature
|
|
|
109
111
|
```
|
|
110
112
|
$ ucn verify expandGlob
|
|
111
113
|
|
|
112
|
-
expandGlob
|
|
114
|
+
Verification: expandGlob
|
|
115
|
+
════════════════════════════════════════════════════════════
|
|
116
|
+
core/discovery.js:191
|
|
117
|
+
expandGlob (pattern: string, options: number = {}) : string[]
|
|
118
|
+
|
|
113
119
|
Expected arguments: 1-2
|
|
114
120
|
|
|
115
|
-
STATUS: ✓ All calls valid
|
|
121
|
+
STATUS: ✓ All calls valid
|
|
122
|
+
Total calls: 7
|
|
123
|
+
Valid: 7
|
|
124
|
+
Mismatches: 0
|
|
125
|
+
Uncertain: 0
|
|
126
|
+
Patterns: 4 in try, 4 in callback
|
|
116
127
|
```
|
|
117
128
|
|
|
129
|
+
The `Patterns:` line surfaces structural classification of each call site — `inLoop`, `inTry`, `inCallback`, `inTestCase`, `awaited` — so you can spot risky call sites (e.g., calls inside loops, missing `await`) at a glance. Same line appears on `impact` and inside `about`.
|
|
130
|
+
|
|
118
131
|
Then preview the refactoring. UCN shows exactly what needs to change and where:
|
|
119
132
|
|
|
120
133
|
```
|
|
121
134
|
$ ucn plan expandGlob --rename-to=expandGlobPattern
|
|
122
135
|
|
|
136
|
+
Refactoring plan: rename
|
|
137
|
+
════════════════════════════════════════════════════════════
|
|
138
|
+
core/discovery.js:191
|
|
139
|
+
|
|
123
140
|
SIGNATURE CHANGE:
|
|
124
|
-
Before: expandGlob (pattern, options = {})
|
|
125
|
-
After: expandGlobPattern (pattern, options = {})
|
|
141
|
+
Before: expandGlob (pattern: string, options: number = {}) : string[]
|
|
142
|
+
After: expandGlobPattern (pattern: string, options: number = {}) : string[]
|
|
126
143
|
|
|
127
|
-
CHANGES NEEDED:
|
|
144
|
+
CHANGES NEEDED: 11
|
|
145
|
+
Files affected: 4
|
|
128
146
|
|
|
129
|
-
|
|
130
|
-
const files = expandGlob(pattern);
|
|
131
|
-
→ const files = expandGlobPattern(pattern);
|
|
147
|
+
BY FILE:
|
|
132
148
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
149
|
+
cli/index.js (2 changes)
|
|
150
|
+
:1190
|
|
151
|
+
const files = expandGlob(pattern);
|
|
152
|
+
→ Rename to: const files = expandGlobPattern(pattern);
|
|
153
|
+
:15
|
|
154
|
+
const { expandGlob, findProjectRoot } = require('../core/discovery');
|
|
155
|
+
→ Update import: const { expandGlobPattern, findProjectRoot } = require('../core/discovery');
|
|
136
156
|
|
|
137
|
-
core/project.js
|
|
138
|
-
const files = expandGlob(pattern, globOpts);
|
|
139
|
-
→ const files = expandGlobPattern(pattern, globOpts);
|
|
157
|
+
... (more changes in core/cache.js, core/project.js, test/integration.test.js)
|
|
140
158
|
```
|
|
141
159
|
|
|
142
160
|
Run `ucn diff-impact --staged` before committing to see what you changed and who calls it.
|
|
143
161
|
|
|
162
|
+
Or wrap the same checks in a single command:
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
$ ucn check --staged
|
|
166
|
+
|
|
167
|
+
Pre-commit Check vs HEAD
|
|
168
|
+
════════════════════════════════════════════════════════════
|
|
169
|
+
Changed: 3 functions
|
|
170
|
+
parseFlags (cli/index.js:165) [MODIFIED] 2 callers
|
|
171
|
+
...
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`ucn check` composes `diff-impact` + `verify` + `affected-tests` in one shot — flags ADDED functions with no callers, signature drift across call sites, and recommends which tests to run.
|
|
175
|
+
|
|
176
|
+
## Get the lay of the land in a new repo
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
$ ucn brief fetch_user
|
|
180
|
+
fetch_user(user_id: int): dict
|
|
181
|
+
svc.py:4-8 (5 lines)
|
|
182
|
+
"Fetch a user from the API."
|
|
183
|
+
async: no | side_effects: [fs, network, process] | complexity: branches=2, depth=2
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
`brief` is the lighter alternative to `about` — typed signature, first sentence of the docstring, side-effect classification, and complexity, all in one screen. Pair with `--git` to see who last touched it and how often.
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
$ ucn doctor
|
|
190
|
+
|
|
191
|
+
UCN Trust Report — /path/to/project
|
|
192
|
+
Index: 144 files, 1569 symbols
|
|
193
|
+
Languages: javascript (74%), typescript (13%), java (4%), python (3%), rust (3%), go (3%)
|
|
194
|
+
Cache: fresh, 221ms build
|
|
195
|
+
...
|
|
196
|
+
Trust level: HIGH
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
`doctor` reports how much UCN trusts the index — file/symbol counts, blind spots (dynamic imports, eval, reflection), parse failures, and a verdict. Use `--deep` to also sample resolution coverage.
|
|
200
|
+
|
|
201
|
+
`entrypoints` lists detected framework handlers (HTTP routes, DI beans, jobs, tests):
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
ucn entrypoints --type=http --framework=spring # narrow to one framework
|
|
205
|
+
ucn entrypoints --exclude-tests # tests are included by default
|
|
206
|
+
```
|
|
207
|
+
|
|
144
208
|
## Find what to clean up
|
|
145
209
|
|
|
146
210
|
Which tests should you run after a change? `affected-tests` walks the blast radius and finds every test that touches the affected functions:
|
|
@@ -148,11 +212,22 @@ Which tests should you run after a change? `affected-tests` walks the blast radi
|
|
|
148
212
|
```
|
|
149
213
|
$ ucn affected-tests expandGlob
|
|
150
214
|
|
|
151
|
-
|
|
152
|
-
|
|
215
|
+
affected-tests: expandGlob
|
|
216
|
+
════════════════════════════════════════════════════════════
|
|
217
|
+
core/discovery.js:191
|
|
218
|
+
1 function changed → 15 functions affected (depth 3)
|
|
219
|
+
|
|
220
|
+
Test files to run (19):
|
|
153
221
|
|
|
154
|
-
|
|
222
|
+
test/integration.test.js (covers: expandGlob, build, idx, setupProject)
|
|
223
|
+
L47: index.build(null, { quiet: true }); [call]
|
|
224
|
+
L167: const files = expandGlob('**/*.go', { root: tmpDir }); [call]
|
|
225
|
+
...
|
|
226
|
+
|
|
227
|
+
Uncovered (10): runGlobCommand, main, runProjectCommand, ...
|
|
155
228
|
⚠ These affected functions have no test references
|
|
229
|
+
|
|
230
|
+
Summary: 15 affected → 19 test files, 5/15 functions covered (33%)
|
|
156
231
|
```
|
|
157
232
|
|
|
158
233
|
## Find unused code
|
|
@@ -160,19 +235,47 @@ Uncovered (7): runGlobCommand, runProjectCommand, ...
|
|
|
160
235
|
```
|
|
161
236
|
$ ucn deadcode --exclude=test
|
|
162
237
|
|
|
163
|
-
Dead code:
|
|
238
|
+
Dead code: 3 unused symbol(s)
|
|
239
|
+
|
|
240
|
+
core/bridge.js
|
|
241
|
+
[ 90- 92] endsWithWildcard (function)
|
|
242
|
+
[ 258- 265] parsePythonDecorator (function)
|
|
243
|
+
core/search.js
|
|
244
|
+
[1409-1445] _testBodyReferencesClass (function)
|
|
245
|
+
|
|
246
|
+
325 exported symbol(s) excluded (all have callers). Use --include-exported to audit them.
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Find missing-await bugs:
|
|
164
250
|
|
|
165
|
-
core/discovery.js
|
|
166
|
-
[ 162- 166] legacyResolve (function)
|
|
167
251
|
```
|
|
252
|
+
ucn audit-async
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Lists async calls inside async functions that lack `await` (JS/TS/Python).
|
|
256
|
+
|
|
257
|
+
## Map your API surface across languages
|
|
258
|
+
|
|
259
|
+
UCN can match server routes to client requests across the supported languages — Express/Fastify/Koa/NestJS/Next.js, Flask/FastAPI, Spring/JAX-RS, Go net/http (Gin/Echo/Chi/Fiber), axum/actix-web on the server side; fetch/axios, requests/httpx, RestTemplate/WebClient, reqwest on the client side.
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
ucn endpoints --bridge
|
|
263
|
+
|
|
264
|
+
# Filters
|
|
265
|
+
ucn endpoints --bridge --unmatched # routes with no client / clients with no server
|
|
266
|
+
ucn endpoints --bridge --method=POST
|
|
267
|
+
ucn endpoints --bridge --prefix=/api
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Match confidence: `EXACT` (literal-literal), `PARTIAL` (server param ↔ client literal), `UNCERTAIN` (template-literal client). Use `--hide-uncertain` to drop the noisy tier.
|
|
168
271
|
|
|
169
272
|
## Extract without reading the whole file
|
|
170
273
|
|
|
171
274
|
```
|
|
172
275
|
$ ucn fn compareNames
|
|
173
276
|
|
|
174
|
-
core/discovery.js:
|
|
175
|
-
[
|
|
277
|
+
core/discovery.js:170
|
|
278
|
+
[ 170- 178] compareNames(a, b)
|
|
176
279
|
────────────────────────────────────────────────────────────
|
|
177
280
|
function compareNames(a, b) {
|
|
178
281
|
const aLower = a.toLowerCase();
|
|
@@ -258,114 +361,7 @@ cp -r "$(npm root -g)/ucn/.claude/skills/ucn" ~/.agents/skills/
|
|
|
258
361
|
|
|
259
362
|
## Full help
|
|
260
363
|
|
|
261
|
-
|
|
262
|
-
UCN - Universal Code Navigator
|
|
263
|
-
|
|
264
|
-
Supported: JavaScript, TypeScript, Python, Go, Rust, Java, HTML
|
|
265
|
-
|
|
266
|
-
Usage:
|
|
267
|
-
ucn [command] [args] Project mode (current directory)
|
|
268
|
-
ucn <file> [command] [args] Single file mode
|
|
269
|
-
ucn <dir> [command] [args] Project mode (specific directory)
|
|
270
|
-
ucn "pattern" [command] [args] Glob pattern mode
|
|
271
|
-
(Default output is text; add --json for machine-readable JSON)
|
|
272
|
-
|
|
273
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
274
|
-
UNDERSTAND CODE
|
|
275
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
276
|
-
about <name> Full picture (definition, callers, callees, tests, code)
|
|
277
|
-
context <name> Who calls this + what it calls (numbered for expand)
|
|
278
|
-
smart <name> Function + all dependencies inline
|
|
279
|
-
impact <name> What breaks if changed (call sites grouped by file)
|
|
280
|
-
blast <name> Transitive blast radius (callers of callers, --depth=N)
|
|
281
|
-
trace <name> Call tree visualization (--depth=N expands all children)
|
|
282
|
-
reverse-trace <name> Upward call chain to entry points (--depth=N, default 5)
|
|
283
|
-
related <name> Find similar functions (same file, shared deps)
|
|
284
|
-
example <name> Best usage example with context
|
|
285
|
-
|
|
286
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
287
|
-
FIND CODE
|
|
288
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
289
|
-
find <name> Find symbol definitions (supports glob: find "handle*")
|
|
290
|
-
usages <name> All usages grouped: definitions, calls, imports, references
|
|
291
|
-
toc Table of contents (compact; --detailed lists all symbols)
|
|
292
|
-
search <term> Text search (regex default, --context=N, --exclude=, --in=)
|
|
293
|
-
Structural: --type=function|class|call --param= --returns= --decorator= --exported --unused
|
|
294
|
-
tests <name> Find test files for a function
|
|
295
|
-
affected-tests <n> Tests affected by a change (blast + test detection, --depth=N)
|
|
296
|
-
|
|
297
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
298
|
-
EXTRACT CODE
|
|
299
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
300
|
-
fn <name>[,n2,...] Extract function(s) (comma-separated for bulk, --file)
|
|
301
|
-
class <name> Extract class
|
|
302
|
-
lines <range> Extract line range (e.g., lines 50-100)
|
|
303
|
-
expand <N> Show code for item N from context output
|
|
304
|
-
|
|
305
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
306
|
-
FILE DEPENDENCIES
|
|
307
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
308
|
-
imports <file> What does file import
|
|
309
|
-
exporters <file> Who imports this file
|
|
310
|
-
file-exports <file> What does file export
|
|
311
|
-
graph <file> Full dependency tree (--depth=N, --direction=imports|importers|both)
|
|
312
|
-
circular-deps Detect circular import chains (--file=, --exclude=)
|
|
313
|
-
|
|
314
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
315
|
-
REFACTORING HELPERS
|
|
316
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
317
|
-
plan <name> Preview refactoring (--add-param, --remove-param, --rename-to)
|
|
318
|
-
verify <name> Check all call sites match signature
|
|
319
|
-
diff-impact What changed in git diff and who calls it (--base, --staged)
|
|
320
|
-
deadcode Find unused functions/classes
|
|
321
|
-
entrypoints Detect framework entry points (routes, DI, tasks)
|
|
322
|
-
|
|
323
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
324
|
-
OTHER
|
|
325
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
326
|
-
api Show exported/public symbols
|
|
327
|
-
typedef <name> Find type definitions
|
|
328
|
-
stats Project statistics (--functions for per-function line counts)
|
|
329
|
-
stacktrace <text> Parse stack trace, show code at each frame (alias: stack)
|
|
330
|
-
|
|
331
|
-
Common Flags:
|
|
332
|
-
--file <pattern> Filter by file path (e.g., --file=routes)
|
|
333
|
-
--exclude=a,b Exclude patterns (e.g., --exclude=test,mock)
|
|
334
|
-
--in=<path> Only in path (e.g., --in=src/core)
|
|
335
|
-
--depth=N Trace/graph depth (default: 3, also expands all children)
|
|
336
|
-
--direction=X Graph direction: imports, importers, or both (default: both)
|
|
337
|
-
--all Expand truncated sections (about, trace, graph, related)
|
|
338
|
-
--top=N Limit results (find, deadcode)
|
|
339
|
-
--limit=N Limit result count (find, usages, search, deadcode, api, toc)
|
|
340
|
-
--max-files=N Max files to index (large projects)
|
|
341
|
-
--context=N Lines of context around matches
|
|
342
|
-
--json Machine-readable output
|
|
343
|
-
--code-only Filter out comments and strings
|
|
344
|
-
--with-types Include type definitions
|
|
345
|
-
--include-tests Include test files
|
|
346
|
-
--class-name=X Scope to specific class (e.g., --class-name=Repository)
|
|
347
|
-
--include-methods Include method calls (obj.fn) in caller/callee analysis
|
|
348
|
-
--include-uncertain Include ambiguous/uncertain matches
|
|
349
|
-
--no-confidence Hide confidence scores (shown by default)
|
|
350
|
-
--min-confidence=N Filter edges below confidence threshold (0.0-1.0)
|
|
351
|
-
--include-exported Include exported symbols in deadcode
|
|
352
|
-
--no-regex Force plain text search (regex is default)
|
|
353
|
-
--functions Show per-function line counts (stats command)
|
|
354
|
-
--include-decorated Include decorated/annotated symbols in deadcode
|
|
355
|
-
--framework=X Filter entrypoints by framework (e.g., --framework=express,spring)
|
|
356
|
-
--exact Exact name match only (find)
|
|
357
|
-
--calls-only Only show call/test-case matches (tests)
|
|
358
|
-
--case-sensitive Case-sensitive text search (search)
|
|
359
|
-
--detailed List all symbols in toc (compact by default)
|
|
360
|
-
--top-level Show only top-level functions in toc
|
|
361
|
-
--max-lines=N Max source lines for class (large classes show summary)
|
|
362
|
-
--no-cache Disable caching
|
|
363
|
-
--clear-cache Clear cache before running
|
|
364
|
-
--base=<ref> Git ref for diff-impact (default: HEAD)
|
|
365
|
-
--staged Analyze staged changes (diff-impact)
|
|
366
|
-
--no-follow-symlinks Don't follow symbolic links
|
|
367
|
-
-i, --interactive Keep index in memory for multiple queries
|
|
368
|
-
```
|
|
364
|
+
Run `ucn --help` for the full command list and flags.
|
|
369
365
|
|
|
370
366
|
---
|
|
371
367
|
|