ucn — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited ucn (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
UCN answers semantic questions about a codebase from a tree-sitter index: where a symbol is defined, who calls it, what it calls, what a change touches, which tests reach it. Every answer labels its evidence and accounts for every line it looked at; nothing is silently dropped.
ucn repo in an unfamiliar repository; --deep adds index health and readiness. Skipped unsupported source is listed with a handoff: use text search and a language-native tool for those files. An UNSUPPORTED or PARTIAL scope is never a semantic zero.ucn find <name> pins a definition. Pass its path:line:name handle to every later command. A plain name that matches several definitions carries an ambiguity warning in show, source, trace, impact, tests, check and plan; never treat the auto-selected definition as the repository-wide target.ucn show <handle> gives the summary, callers and callees. Add --sections=source,tests,types,dependencies,example,related for more.ucn impact <handle> and ucn tests <handle> --depth=3.ucn check <handle>; before committing: target-less ucn check. Both compare a changed declaration with its parameters at --base (default HEAD), so the call sites bound to the old declaration are checked against the new one; a site that fits no remaining overload is a mismatch, never an excluded other-target line.ucn source <handle> or ucn source path/to/file:10-30 for exact code, only when inspection is needed.| Decision | Command | |
|---|---|---|
| Orient or diagnose a repository | ucn repo [--sections=files,stats,health] [--deep] | |
| Understand one symbol | ucn show <handle> [--sections=...] | |
| Locate definitions or types | ucn find <name> [--type=type] | |
| Inspect literal-name occurrence kinds | ucn usages <name> | |
| Search literal text, explicit regex, or AST structure | ucn search [term] [--regex] [--type=...] | |
| Extract exact source | `ucn source <handle\ | file:range>` |
| Follow calls down or up | `ucn trace <handle> --direction=callees\ | callers` |
| Find paths to roots | ucn trace <handle> --direction=callers --to=entrypoints | |
| Assess direct or Git-diff impact | ucn impact [handle] | |
| Select direct or transitive tests | ucn tests <handle> [--depth=N] | |
| Validate a symbol or pending diff | ucn check [handle] | |
| Preview a refactor | ucn plan <handle> --rename-to=X | |
| Inspect file dependencies | ucn deps <file> [--direction=...] | |
| Find circular imports | ucn deps --cycles (project-wide; no file target) | |
| Inspect public surface | ucn api [file] | |
| Review entry points or HTTP routes | ucn entrypoints; ucn endpoints | |
| Generate review candidates | ucn deadcode; ucn audit-async | |
| Resolve runtime frames | ucn stacktrace <text> |
Caller-bearing views (show, impact, trace, tests, check) tier every candidate:
CONFIRMED: binding, receiver, import, or ownership evidence for the pinned target.UNVERIFIED: call syntax that may reach the target, with the reason identity could not be established. Review it before a breaking change. When same-name definitions compete, show lists their stable handles once above the sites.ACCOUNT, each with its reason in JSON.Trust lines close every answer and survive truncation:
ACCOUNT partitions every line where the name occurs: confirmed, unverified, non-call (definition, import, reference, other text), other-target, unaccounted. In mixed-language repositories it also counts occurrences in unsupported-language source files.CONTRACT states what that partition covers. Semantic completeness is never claimed: aliases, generated code, reflection and runtime dispatch may exist.WARNING lists unreadable, unparsed or partially indexed files and unsupported-language occurrence sites with their line text, so nothing text search would show is hidden. usages and tests carry the same disclosure as a note.FILTERED means query options hid evidence. CALLEE ACCOUNT and TREE ACCOUNT do the same for callees and trace trees.A property/getter/setter target adds PROPERTY ACCESS SITES to impact (reads and writes with access kind; receiver identity confirms, an unresolved receiver stays unverified). A type target adds TYPE REFERENCE SITES (confirmed by an import link to the definition's file, or package scope in Go/Java). DEPENDENCY SITES counts them; CALL SITES stays call-shaped. Target-less impact and check diff the working tree against HEAD (--staged for the index), include untracked non-ignored source as whole-file additions, and put classes, interfaces, types and fields in declaration bands; a modified or deleted declaration makes check BLOCKED until reviewed with the language toolchain.
Numeric evidence values are ordinal ranking weights, not probabilities. An observed-text zero is not a semantic zero or safe-delete proof.
--lines and --raw make ucn compose like grep -n:
ucn find handleRequest --lines # path:line:signature # kind
ucn show handleRequest --lines # callers as path:line:text; unverified ones end in "\t# unverified: <reason>"
ucn show handleRequest --lines --sections=callees
ucn usages handleRequest --lines # every literal-name line; kinds tagged "# import" / "# definition" / "# reference"
ucn search 'retry(' --lines # grep -n output, code-aware scope
ucn impact handleRequest --lines
ucn source handleRequest --raw # the code and nothing else, ready for an exact-string edit
ucn source src/server.js:40-80 --rawRecords go to stdout; ACCOUNT/CONTRACT, notes and same-name disambiguation go to stderr as # lines (MCP keeps them in the one text block; --raw appends its note as one trailing # line there). --lines has no default row cap; explicit --top/--limit disclose what they omit; an explicit --max-chars fails before any output instead of truncating records. grep -v '# unverified' keeps the confirmed tier. usages --lines emits one record per source line and tags combined kinds; JSON keeps individual occurrences. show --lines accepts only the callers/callees sections (default callers); target-less impact --lines lists Git-diff callers with per-target accounting. source --raw extracts whole functions and large classes; --max-lines truncation is disclosed on stderr. Unusual path characters (backslash, tab, CR, LF) are escaped; use --json for exact filenames, and for trace/tests scripting. Closing the pipe with head is supported.
Exit codes: 0 success; 1 for an empty --lines listing, a blocking check (target-less check with TRUST: BLOCKED, or check <handle> reporting a mismatch or an unverified call site), or a JSON command error (meta.ok: false plus error); 2 for a text-mode command error or a check that could not run. An exception inside UCN prints Internal error: ... on every surface (CLI JSON adds meta.internalError: true); it says nothing about the code, so rerun with a narrower target or report it.
CLI, MCP and interactive mode run the same 18 commands through one registry, the same handlers and the same formatters. CLI spells multiword commands with hyphens (audit-async), MCP uses snake case (audit_async) through one ucn tool. --json returns { meta, data }: meta.command keeps the surface spelling and may add canonicalCommand, meta.contract carries the truth boundary, and public file paths are relative to meta.pathBase. Definition handles start at a decorator when present; nameLine is the declaration token's line.
Text output has a character budget on both CLI and MCP: 3K for broad sweeps (repo, entrypoints, endpoints, deadcode, deps, check, audit-async), 10K for every other command, 100K ceiling (--max-chars=N / max_chars; --all lifts caps where a command supports it). Room for every trust line is reserved before any body text. A truncated answer keeps its head, a notice with the full size and the limit, and the trust lines; show and impact keep a head of every tier with a +N more line each, so a long confirmed list never hides the unverified band. A budget too small for the trust lines withholds the answer and names the budget that would carry them (answer withheld; 0 of 3 trust line(s) shown. Raise --max-chars to at least 498.). Narrow with a handle, --file, --in or --sections before raising the budget.
Indexes live in a per-user, project-keyed cache outside the repository (UCN_CACHE_DIR overrides the root; --no-cache bypasses it; --clear-cache removes the project's cache; a .ucn-cache directory left in a project is migrated on first use). MCP keeps the process and index warm across calls. Concurrent cold starts share one build: the first process takes a build lock and the others wait for its cache (Waiting for another ucn process building the index... on stderr); a lock left by a dead process is broken automatically.
Discovery applies the project's .gitignore files (root and nested) with git's own matching rules; git-tracked files are indexed even when a rule matches them, and a failing git ls-files is disclosed as a partial index (git-listing-failed in repo --sections=health and in caller contracts), never a silently smaller one. *.min.js, *.bundle.js and *.map are skipped and disclosed, which makes observed-text completeness partial; --include-bundled (MCP include_bundled=true) indexes the JavaScript bundles, respecting user exclusions and bypassing the shared cache. Source maps stay unindexed; inspect them with text tools.
C/C++ uses compile_commands.json when present for header classification and include paths. Project C/C++ function-like macros and Rust macro_rules! invocations are expanded, and what they generate is indexed at the invocation ([via macro NAME]). This is portable AST analysis, not a compiler build: macros, templates, generated code, reflection and external dependency semantics can stay unverified, and no conditional branch is asserted as the one a build activates.
find.impact; review every unverified, excluded, filtered, and warning entry.trace --direction=callers for transitive behavioral impact.tests --depth=3; treat paths without static test links as test-planning signals, not runtime coverage proof.check <handle>, the relevant compiler/type checker, and selected tests.check to reconcile the repository diff.deadcode is a candidate generator, never deletion proof. Before deleting, inspect usages, impact, entrypoints, api, and repo --sections=health --deep, then corroborate with the compiler/type checker and tests. Members that reflection (exact names or literal-fragment patterns), computed dispatch, runtime protocols (Python dunders, Java serialization callbacks, C# pattern members, JS toJSON/then), unknown decorators, event-handler assignment, an outside base class, or macro expansion may reach are withheld or warned; the deadcode notes in the command reference list them. Never delete solely from deadcode or an observed-text-zero result.
--class-name or --file only when a handle is unavailable.--sections to request only the show or repo evidence needed.--expand-unverified only when deliberately exploring possible caller chains; those descendants remain possible, not confirmed.--all only when that command's output reports a supported cap; otherwise narrow the query or raise --max-chars.search or ordinary repository search for text, filenames, configuration, and unsupported syntax.find activity counts, usages inventory, plan rename closure, endpoints matching, deadcode withholding, audit-async findings, deps --cycles).~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.