@phnx-labs/agents-cli 1.20.9 → 1.20.10

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/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ **`agents inspect .` reads the project `.agents/`, and plugin drill-down shows bundled skills**
6
+
7
+ - `agents inspect .` (and any path to a repo root) now resolves to the project's nested `.agents/` tree when that tree is a populated DotAgents root, instead of the project root itself. Previously a top-level `agents.yaml` version-pin or an unrelated source `skills/` dir at the repo root was mistaken for a DotAgents root, so `inspect .` reported the wrong directory's resources (e.g. `plugins 0` while the real `.agents/plugins/` held a plugin). A bare `.agents`-named dir still resolves to itself, and standalone clones / extra repos that keep resources at the top level (using `.agents/` only for worktrees) are unaffected — their nested `.agents/` is not a DotAgents root, so the top level still wins.
8
+ - `agents inspect <repo> --plugins` now reads plugin bundles through the plugin discoverer: the list shows each plugin's manifest description, and drilling into one (`--plugins <name>`) reports its bundled skills, commands, subagents, hooks, MCP servers, and version. Previously plugins were treated as opaque directories with no description and no view into what they ship.
9
+
5
10
  **Single-typo agent names auto-correct everywhere, not just `agents run`**
6
11
 
7
12
  - `agents view cladue` used to print `Unknown agent 'cladue'` even though `agents run cladue` auto-corrected. `resolveAgentName` — the canonical resolver behind `view`, `usage`, `inspect`, `doctor`, `sync`, `models`, `skills`, `hooks`, `import`, `sessions --agent`, and every `agent@version` spec (`agents add claud@latest`, `agents use codx@2.1.170`) — now falls back to Damerau-Levenshtein distance-1 matching against canonical ids and multi-letter aliases: `cladue` -> `claude` (transposition), `kim` -> `kimi`, `codx` -> `codex`, `gemni` -> `gemini`.
@@ -24,6 +24,8 @@ interface ResourceItem {
24
24
  linkTarget: string;
25
25
  /** One-line description (frontmatter `description:` or first non-frontmatter line). */
26
26
  description: string;
27
+ /** Extra detail rows surfaced in detail mode (e.g. a plugin's bundled skills/commands). */
28
+ extra?: Array<[string, string]>;
27
29
  }
28
30
  interface InspectOptions {
29
31
  brief?: boolean;
@@ -23,7 +23,7 @@ import { readMeta, getUserAgentsDir, getSystemAgentsDir, getProjectAgentsDir, ge
23
23
  import { getVersionHomePath } from '../lib/versions.js';
24
24
  import { getShimsDir, getVersionedAliasPath } from '../lib/shims.js';
25
25
  import { getAgentResources, listResources, } from '../lib/resources.js';
26
- import { discoverPlugins } from '../lib/plugins.js';
26
+ import { discoverPlugins, discoverPluginsInDir } from '../lib/plugins.js';
27
27
  import { countSessionsInScope } from '../lib/session/discover.js';
28
28
  import { damerauLevenshtein } from '../lib/fuzzy.js';
29
29
  /** Resource kinds the inspect command can drill into. */
@@ -161,18 +161,23 @@ export function resolveRepoTarget(target, cwd) {
161
161
  const stat = safeStat(abs);
162
162
  if (!stat || !stat.isDirectory())
163
163
  return null;
164
- // A dir that is itself a DotAgents root wins over its nested .agents/ —
165
- // extra repos like ~/.agents-extras keep resources at the top level and use
166
- // .agents/ only for worktrees.
164
+ // A dir literally named `.agents` is the root itself.
165
+ if (path.basename(abs) === '.agents') {
166
+ return { label: path.basename(path.dirname(abs)), root: abs };
167
+ }
168
+ // A nested `.agents/` that is a populated DotAgents root wins over `abs` — the
169
+ // project case (`agents inspect .` from a repo root whose resources live under
170
+ // `.agents/`, while the repo's own top-level `skills/`, `agents.yaml` pin, etc.
171
+ // are unrelated source, not a DotAgents tree).
172
+ const nested = path.join(abs, '.agents');
173
+ if (isDotAgentsRoot(nested)) {
174
+ return { label: path.basename(abs), root: nested };
175
+ }
176
+ // Otherwise treat `abs` itself as the root: standalone clones and extra repos
177
+ // like ~/.agents-extras keep resources at the top level and use `.agents/`
178
+ // only for worktrees (so their nested `.agents/` is not a DotAgents root).
167
179
  if (isDotAgentsRoot(abs)) {
168
- const label = path.basename(abs) === '.agents' ? path.basename(path.dirname(abs)) : path.basename(abs);
169
- return { label, root: abs };
170
- }
171
- if (path.basename(abs) !== '.agents') {
172
- const nested = path.join(abs, '.agents');
173
- if (safeStat(nested)?.isDirectory()) {
174
- return { label: path.basename(abs), root: nested };
175
- }
180
+ return { label: path.basename(abs), root: abs };
176
181
  }
177
182
  return null;
178
183
  }
@@ -204,6 +209,14 @@ async function inspectRepo(repo, options) {
204
209
  }
205
210
  /** List one resource kind from a single repo root — no layering, no overrides. */
206
211
  export function collectRepoKind(repo, kind) {
212
+ // Plugins are bundles with a manifest + nested skills/commands/hooks — read
213
+ // them through the plugin discoverer so the manifest description and bundled
214
+ // resources surface, rather than treating each as an opaque directory.
215
+ if (kind === 'plugins') {
216
+ return discoverPluginsInDir(path.join(repo.root, 'plugins'))
217
+ .map(p => pluginToItem(p, repo.label))
218
+ .sort((a, b) => a.name.localeCompare(b.name));
219
+ }
207
220
  const dir = path.join(repo.root, kind);
208
221
  let entries;
209
222
  try {
@@ -486,14 +499,35 @@ function collectKind(agent, versionHome, kind) {
486
499
  }
487
500
  }
488
501
  function pluginItems() {
489
- const plugins = discoverPlugins();
490
- return plugins.map(p => ({
491
- name: p.name,
492
- source: 'user',
493
- path: p.root,
494
- linkTarget: linkTarget(p.root),
495
- description: p.manifest.description ?? '',
496
- }));
502
+ return discoverPlugins().map(p => pluginToItem(p, 'user'));
503
+ }
504
+ /**
505
+ * Map a discovered plugin to a resource item, surfacing the manifest description
506
+ * and the bundle's nested resources (skills, commands, hooks, ...) as detail rows.
507
+ */
508
+ function pluginToItem(plugin, source) {
509
+ const extra = [];
510
+ const list = (names) => names.length <= 8 ? names.join(', ') : `${names.slice(0, 8).join(', ')}, +${names.length - 8} more`;
511
+ if (plugin.skills.length)
512
+ extra.push(['skills', `${plugin.skills.length} (${list(plugin.skills)})`]);
513
+ if (plugin.commands.length)
514
+ extra.push(['commands', `${plugin.commands.length} (${list(plugin.commands)})`]);
515
+ if (plugin.agentDefs.length)
516
+ extra.push(['subagents', `${plugin.agentDefs.length} (${list(plugin.agentDefs)})`]);
517
+ if (plugin.hooks.length)
518
+ extra.push(['hooks', String(plugin.hooks.length)]);
519
+ if (plugin.mcpServers.length)
520
+ extra.push(['mcp', list(plugin.mcpServers)]);
521
+ if (plugin.manifest.version)
522
+ extra.push(['version', plugin.manifest.version]);
523
+ return {
524
+ name: plugin.name,
525
+ source,
526
+ path: plugin.root,
527
+ linkTarget: linkTarget(plugin.root),
528
+ description: plugin.manifest.description ?? '',
529
+ extra,
530
+ };
497
531
  }
498
532
  function entriesFromAgentResources(agent, versionHome, kind) {
499
533
  const res = getAgentResources(agent, { home: versionHome });
@@ -562,6 +596,10 @@ function buildDetailRows(item, kind) {
562
596
  rows.push(['tools', fm.tools.join(', ')]);
563
597
  }
564
598
  }
599
+ // Plugin bundles carry their nested resources as pre-built rows.
600
+ if (kind === 'plugins' && item.extra) {
601
+ rows.push(...item.extra);
602
+ }
565
603
  return rows;
566
604
  }
567
605
  function findMatches(items, query) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phnx-labs/agents-cli",
3
- "version": "1.20.9",
3
+ "version": "1.20.10",
4
4
  "description": "One CLI for all your AI coding agents - versions, config, cloud dispatch, sessions, and teams (now with first-class Grok Build CLI support)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",