$npx -y skills add matlab/matlab-agentic-toolkit --skill matlab-analyze-dependenciesAnalyze the effective toolbox file set to produce a Dependency Manifest — classify all transitive dependencies as included, product, add-on, or external-unresolved, then present resolution options with tradeoffs. Use after matlab-define-toolbox-api when the spec is approved.
| 1 | # matlab-analyze-dependencies — Dependency Analyzer |
| 2 | |
| 3 | You produce the **Dependency Manifest**: a complete picture of what the toolbox needs at runtime, what ships inside the .mltbx, and what doesn't. For anything that doesn't ship, you explain why and present resolution options. |
| 4 | |
| 5 | ## When to Use |
| 6 | |
| 7 | - After `matlab-define-toolbox-api` spec is approved, or user asks "what does this code depend on?" |
| 8 | - Re-running after code changes to update the manifest |
| 9 | |
| 10 | ## When NOT to Use |
| 11 | |
| 12 | - Writing code or fixing bugs — this skill only analyzes, it does not modify source |
| 13 | - Building the .mltbx — use `matlab-build-toolbox` after dependencies are resolved |
| 14 | - Initial project setup — use `matlab-define-toolbox-api` first to define the toolbox spec |
| 15 | |
| 16 | ## Key Functions |
| 17 | |
| 18 | | Function | Purpose | |
| 19 | |----------|---------| |
| 20 | | `matlab.addons.toolbox.ToolboxOptions` | Determine effective file set (what ships) | |
| 21 | | `matlab.codetools.requiredFilesAndProducts` | Trace transitive file and product dependencies | |
| 22 | | `which` | Resolve namespace-qualified function names | |
| 23 | | `exist` | Check if bare function names resolve | |
| 24 | | `matlab.addons.installedAddons` | Correlate add-on file paths with metadata | |
| 25 | |
| 26 | ## Critical Pitfalls |
| 27 | |
| 28 | These three issues cause **silent failures** — no error is raised, but classification results are wrong. Always apply these fixes. |
| 29 | |
| 30 | ### Pitfall 1: Path Separator Mismatch (Windows) |
| 31 | |
| 32 | On Windows, `fList` returns backslashes regardless of input. If `toolboxRoot` has forward slashes, `startsWith(fList, toolboxRoot)` silently returns false for every file. **Normalize both before any comparison:** |
| 33 | |
| 34 | ```matlab |
| 35 | toolboxRoot = replace(toolboxRoot, '/', filesep); |
| 36 | fList = replace(fList, '/', filesep); |
| 37 | ``` |
| 38 | |
| 39 | ### Pitfall 2: matlabroot File Leak |
| 40 | |
| 41 | Files under `matlabroot` (e.g., `toolbox/local/userpath.m`) occasionally appear in `fList` because they live in non-product folder structures. **Filter them out:** |
| 42 | |
| 43 | ```matlab |
| 44 | mroot = matlabroot; |
| 45 | fList = fList(~startsWith(fList, mroot)); |
| 46 | ``` |
| 47 | |
| 48 | ### Pitfall 3: Namespace Resolution Requires which() |
| 49 | |
| 50 | `exist('pkg.subpkg.func', 'file')` returns **0** even when the function is valid and on the path. For any dotted/namespace-qualified name, use `which()` instead: |
| 51 | |
| 52 | ```matlab |
| 53 | % exist() FAILS for namespace calls: |
| 54 | exist('statskit.internal.computeRange', 'file') % returns 0 (wrong!) |
| 55 | |
| 56 | % which() WORKS: |
| 57 | which('statskit.internal.computeRange') % returns full path |
| 58 | ``` |
| 59 | |
| 60 | **Resolution strategy:** |
| 61 | - Bare names (no dots): `exist(name, 'file') > 0 || exist(name, 'builtin') > 0` |
| 62 | - Dotted names: `~isempty(which(name))` |
| 63 | |
| 64 | ## Core Concepts |
| 65 | |
| 66 | **The Packaging Constraint:** An .mltbx can only contain files inside the toolbox root folder. External files cannot be pulled in at install time. The only options are: copy in, declare add-on dependency, Additional Software (URL zip), or refactor. |
| 67 | |
| 68 | **The Effective File Set:** All files in toolbox root minus those excluded by the ignore file and default exclusions. Use `ToolboxOptions` to determine this authoritatively. The ignore file may be named `toolbox.ignore` (R2026a and earlier) or `package.ignore` (R2026b+). Check for both — `ToolboxOptions` handles whichever is present. |
| 69 | |
| 70 | ## Workflow |
| 71 | |
| 72 | ### Phase 1 — Determine the Effective File Set |
| 73 | |
| 74 | ```matlab |
| 75 | identifier = matlab.lang.internal.uuid(); |
| 76 | opts = matlab.addons.toolbox.ToolboxOptions(toolboxRoot, identifier); |
| 77 | effectiveFiles = opts.ToolboxFiles; |
| 78 | ``` |
| 79 | |
| 80 | Do not reimplement ignore-file logic manually. `ToolboxOptions` handles both file names, default exclusions, and edge cases. |
| 81 | |
| 82 | ### Phase 2 — Trace Dependencies |
| 83 | |
| 84 | ```matlab |
| 85 | mFiles = effectiveFiles(endsWith(effectiveFiles, ".m") | endsWith(effectiveFiles, ".mlx")); |
| 86 | [fList, pList] = matlab.codetools.requiredFilesAndProducts(mFiles); |
| 87 | fList = string(fList(:)); |
| 88 | ``` |
| 89 | |
| 90 | Apply Pitfall 1 (normalize paths) and Pitfall 2 (filter matlabroot) **immediately after** getting fList, before any classification. |
| 91 | |
| 92 | **Classify files in fList:** |
| 93 | - **Included**: starts with `toolboxRoot` and in effective set |
| 94 | - **Add-on**: under `fullfile(getenv('APPDATA'), 'MathWorks', 'MATLAB Add-Ons')` |
| 95 | - **External unresolved**: everything else — requires user decision |
| 96 | |
| 97 | **Classify products from pList:** |
| 98 | - `Certain == 1`: confirmed product dependency — declare in metadata |
| 99 | - `Certain == 0`: heuristic guess — flag for user confirmation |
| 100 | |
| 101 | **Check ignore conflicts:** Files inside toolbox root that are in `fList` but NOT in `effectiveFiles` — code needs them but they won't ship. |
| 102 | |
| 103 | **Check runtime file references:** `fList` never contains data files (.mat, .csv, images, etc.). Scan `.m` files for I/O functions with string-literal path arguments to detect files |