@pkgseer/cli 0.2.4 → 0.2.5

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 CHANGED
@@ -2,120 +2,209 @@
2
2
 
3
3
  CLI and MCP server for [PkgSeer](https://pkgseer.dev) — package intelligence for developers and AI assistants.
4
4
 
5
- Get insights about packages across npm, PyPI, and Hex registries: metadata, security vulnerabilities, dependencies, and quality metrics. Works standalone or as an MCP server for AI assistants like Claude and Cursor.
5
+ Get insights about packages across npm, PyPI, Hex, and crates.io registries: search code and documentation, check security vulnerabilities, analyze dependencies, and compare packages. Works standalone or as an MCP server for AI assistants like Claude and Cursor.
6
6
 
7
7
  ## Installation
8
8
 
9
- The easiest way to get started is using npx no installation required:
9
+ Use npx without installation:
10
10
 
11
11
  ```bash
12
12
  npx @pkgseer/cli --help
13
13
  ```
14
14
 
15
- For frequent use, install globally:
15
+ Or install globally:
16
16
 
17
17
  ```bash
18
18
  npm install -g @pkgseer/cli
19
19
  ```
20
20
 
21
- ## Getting Started
21
+ ## Quick Start
22
22
 
23
- ### 1. Authenticate (Recommended)
23
+ ```bash
24
+ # Interactive setup (recommended for first-time users)
25
+ pkgseer init
26
+
27
+ # Or set up manually:
28
+ pkgseer login # Authenticate with your PkgSeer account
29
+ pkgseer skill init # Install as AI assistant skill
30
+ ```
31
+
32
+ ## AI Assistant Integration
33
+
34
+ PkgSeer works with AI assistants in two ways:
24
35
 
25
- While you can use PkgSeer without authentication, logging in gives you higher rate limits and access to all features:
36
+ ### Skills
37
+
38
+ Skills teach your AI assistant to use PkgSeer CLI commands through natural language:
26
39
 
27
40
  ```bash
28
- pkgseer login
41
+ pkgseer skill init
29
42
  ```
30
43
 
31
- This opens your browser to authenticate with your PkgSeer account. Your credentials are stored securely in `~/.pkgseer/`.
44
+ This installs a skill definition for Claude Code or Codex CLI. The AI runs CLI commands and reads the output.
45
+
46
+ ### MCP Server
32
47
 
33
- To check your authentication status:
48
+ MCP provides structured tools that AI assistants can call programmatically:
34
49
 
35
50
  ```bash
36
- pkgseer auth status
51
+ pkgseer mcp init
37
52
  ```
38
53
 
39
- ### 2. Use with AI Assistants
40
-
41
- The main use case for this CLI is as an MCP (Model Context Protocol) server that gives AI assistants access to package intelligence.
54
+ This provides structured tools that AI assistants can call programmatically. Configuration varies by assistant:
42
55
 
43
- #### Cursor IDE
56
+ **Claude Code / Codex CLI**: The `mcp init` command configures these automatically.
44
57
 
45
- Add this to your `.cursor/mcp.json` file:
58
+ **Cursor IDE**: Add to `.cursor/mcp.json`:
46
59
 
47
60
  ```json
48
61
  {
49
62
  "mcpServers": {
50
63
  "pkgseer": {
51
64
  "command": "npx",
52
- "args": ["-y", "@pkgseer/cli", "mcp"]
65
+ "args": ["-y", "@pkgseer/cli", "mcp", "start"]
53
66
  }
54
67
  }
55
68
  }
56
69
  ```
57
70
 
58
- #### Claude Desktop
59
-
60
- Add this to your Claude Desktop configuration file:
61
-
62
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
63
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
71
+ **Claude Desktop**: Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
64
72
 
65
73
  ```json
66
74
  {
67
75
  "mcpServers": {
68
76
  "pkgseer": {
69
77
  "command": "npx",
70
- "args": ["-y", "@pkgseer/cli", "mcp"]
78
+ "args": ["-y", "@pkgseer/cli", "mcp", "start"]
71
79
  }
72
80
  }
73
81
  }
74
82
  ```
75
83
 
76
- Once configured, your AI assistant can use tools to answer questions like:
84
+ ## CLI Commands
77
85
 
78
- - "What security vulnerabilities does lodash have?"
79
- - "Compare react vs preact vs solid-js"
80
- - "What are the dependencies of express?"
86
+ ### Search
81
87
 
82
- #### Prompt for AI Assistants
88
+ Search code and documentation across packages:
83
89
 
84
- To help your AI assistant use PkgSeer proactively, add this to your project rules (`.cursor/rules`, `AGENTS.md`, or similar):
90
+ ```bash
91
+ # Search in specific packages
92
+ pkgseer search "authentication" -P express,passport
93
+ pkgseer search "http client" -P pypi:requests,pypi:httpx
94
+ pkgseer search "json parsing" -P hex:jason,hex:poison
95
+
96
+ # Search modes
97
+ pkgseer search "auth" -P lodash --mode code # Code only
98
+ pkgseer search "auth" -P lodash --mode docs # Docs only
99
+ ```
85
100
 
86
- ```markdown
87
- When working with dependencies:
101
+ ### Package Commands
88
102
 
89
- - Use PkgSeer MCP tools to check for security vulnerabilities before adding new packages
90
- - Compare package alternatives with compare_packages when multiple options exist
91
- - Review package quality metrics to ensure dependencies are well-maintained
103
+ ```bash
104
+ pkgseer pkg info lodash # Package summary and metadata
105
+ pkgseer pkg vulns lodash@4.17.21 # Security vulnerabilities
106
+ pkgseer pkg quality express # Quality score (0-100)
107
+ pkgseer pkg deps express # Direct dependencies
108
+ pkgseer pkg deps express --transitive # Include transitive deps
109
+ pkgseer pkg compare axios got fetch-h2 # Compare packages
92
110
  ```
93
111
 
94
- ## Available Tools
112
+ Package format: `[registry:]name[@version]`
113
+ - `lodash` — npm (default registry)
114
+ - `pypi:requests` — PyPI
115
+ - `hex:phoenix` — Hex
116
+ - `crates:serde` — crates.io
117
+ - `lodash@4.17.21` — specific version
118
+
119
+ ### Documentation Commands
95
120
 
96
- When running as an MCP server, the following tools are available to AI assistants:
121
+ ```bash
122
+ pkgseer docs list pypi:requests # List available doc pages
123
+ pkgseer docs get lodash/chunk # Fetch specific doc page
124
+ pkgseer docs search "routing" -P express # Search docs only
125
+ ```
97
126
 
98
- | Tool | What it does |
99
- | ------------------------- | ----------------------------------------------------------------------------------- |
100
- | `package_summary` | Get package metadata, latest versions, security advisories, and quickstart examples |
101
- | `package_vulnerabilities` | Find known security vulnerabilities affecting a package |
102
- | `package_dependencies` | Explore the dependency tree (direct and transitive) |
103
- | `package_quality` | View quality metrics and maintenance scores |
104
- | `compare_packages` | Compare multiple packages side-by-side |
127
+ ### Project Commands
105
128
 
106
- All tools work with **npm**, **PyPI**, and **Hex** registries.
129
+ ```bash
130
+ pkgseer project init # Create pkgseer.yml config
131
+ pkgseer project detect # Detect package manifests
132
+ pkgseer project upload # Upload project to PkgSeer
133
+ ```
107
134
 
108
- ## CLI Commands
135
+ ### Authentication
109
136
 
110
137
  ```bash
111
- pkgseer --help # Show all available commands
112
- pkgseer --version # Show version number
138
+ pkgseer login # Authenticate via browser
139
+ pkgseer logout # Sign out
140
+ pkgseer auth status # Check authentication state
141
+ ```
142
+
143
+ ### Configuration
144
+
145
+ ```bash
146
+ pkgseer config show # Display current configuration
147
+ ```
148
+
149
+ ## MCP Tools
150
+
151
+ When running as an MCP server, these tools are available:
152
+
153
+ | Tool | Description |
154
+ |------|-------------|
155
+ | `package_summary` | Package metadata, versions, quickstart examples |
156
+ | `package_vulnerabilities` | Security advisories and CVEs |
157
+ | `package_dependencies` | Dependency tree (direct and transitive) |
158
+ | `package_quality` | Quality score with category breakdown |
159
+ | `compare_packages` | Side-by-side comparison of packages |
160
+ | `list_package_docs` | Available documentation pages |
161
+ | `fetch_package_doc` | Full content of a documentation page |
162
+ | `search` | Search code and docs across packages |
163
+ | `fetch_code_context` | Fetch code from search results |
164
+ | `search_project_docs` | Search docs for packages in current project |
165
+
166
+ ## Configuration
167
+
168
+ ### Project Configuration
113
169
 
114
- pkgseer login # Authenticate with your PkgSeer account
115
- pkgseer logout # Sign out and clear stored credentials
116
- pkgseer auth status # Check if you're logged in and token validity
170
+ Create `pkgseer.yml` in your project root:
117
171
 
118
- pkgseer mcp # Start the MCP server (for AI assistant integration)
172
+ ```yaml
173
+ project: my-project-name
174
+
175
+ # Optional: limit which tools are available
176
+ enabled_tools:
177
+ - package_summary
178
+ - package_vulnerabilities
179
+ - search_project_docs
180
+ ```
181
+
182
+ ### Environment Variables
183
+
184
+ | Variable | Description |
185
+ |----------|-------------|
186
+ | `PKGSEER_API_TOKEN` | API token (alternative to `pkgseer login`) |
187
+ | `PKGSEER_URL` | Base URL for PkgSeer (for development/testing) |
188
+
189
+ ## Documentation
190
+
191
+ - [Architecture Overview](docs/implementation/architecture.md)
192
+ - [MCP Installation Guide](docs/implementation/mcp-installation.md)
193
+ - [Creating MCP Tools](docs/implementation/tools.md)
194
+ - [Authentication Flow](docs/implementation/auth.md)
195
+ - [Skills System](docs/implementation/skills.md)
196
+ - [Configuration Reference](docs/implementation/configuration.md)
197
+
198
+ ## Development
199
+
200
+ See [CLAUDE.md](CLAUDE.md) for development guidelines.
201
+
202
+ ```bash
203
+ bun install # Install dependencies
204
+ bun run dev # Development mode
205
+ bun test # Run tests
206
+ bun run build # Build for production
207
+ bun run codegen # Regenerate GraphQL types
119
208
  ```
120
209
 
121
210
  ## Need Help?
@@ -125,4 +214,4 @@ pkgseer mcp # Start the MCP server (for AI assistant integration)
125
214
 
126
215
  ## License
127
216
 
128
- MIT © [Juha Litola](https://github.com/pkgseer)
217
+ (c) 2025-2026 Juha Litola
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  version
4
- } from "./shared/chunk-48mwa8wt.js";
4
+ } from "./shared/chunk-drz16bhv.js";
5
5
 
6
6
  // src/cli.ts
7
7
  import { Command } from "commander";
@@ -1789,7 +1789,7 @@ function parsePackageSpec(spec) {
1789
1789
  if (spec.includes(":")) {
1790
1790
  const colonIndex = spec.indexOf(":");
1791
1791
  const potentialRegistry = spec.slice(0, colonIndex).toLowerCase();
1792
- if (["npm", "pypi", "hex"].includes(potentialRegistry)) {
1792
+ if (["npm", "pypi", "hex", "crates"].includes(potentialRegistry)) {
1793
1793
  registry = potentialRegistry;
1794
1794
  rest = spec.slice(colonIndex + 1);
1795
1795
  }
@@ -1808,7 +1808,8 @@ function toGraphQLRegistry(registry) {
1808
1808
  const map = {
1809
1809
  npm: "NPM",
1810
1810
  pypi: "PYPI",
1811
- hex: "HEX"
1811
+ hex: "HEX",
1812
+ crates: "CRATES"
1812
1813
  };
1813
1814
  return map[registry.toLowerCase()] || "NPM";
1814
1815
  }
@@ -2559,7 +2560,7 @@ function abbrevLang(lang) {
2559
2560
  function truncate(text, maxLen) {
2560
2561
  if (text.length <= maxLen)
2561
2562
  return text;
2562
- return text.slice(0, maxLen - 3) + "...";
2563
+ return `${text.slice(0, maxLen - 3)}...`;
2563
2564
  }
2564
2565
  function formatEntryCompact(entry, useColors) {
2565
2566
  if (!entry)
@@ -3319,7 +3320,7 @@ function shouldIgnorePath(relativePath, patterns) {
3319
3320
  return ignored;
3320
3321
  }
3321
3322
  function shouldIgnoreDirectory(relativeDirPath, patterns) {
3322
- const normalized = relativeDirPath.replace(/\\/g, "/").replace(/\/$/, "") + "/";
3323
+ const normalized = `${relativeDirPath.replace(/\\/g, "/").replace(/\/$/, "")}/`;
3323
3324
  return shouldIgnorePath(normalized, patterns);
3324
3325
  }
3325
3326
 
@@ -3352,6 +3353,10 @@ var MANIFEST_TYPES = [
3352
3353
  {
3353
3354
  type: "hex",
3354
3355
  filenames: ["mix.exs", "mix.lock"]
3356
+ },
3357
+ {
3358
+ type: "crates",
3359
+ filenames: ["Cargo.toml", "Cargo.lock"]
3355
3360
  }
3356
3361
  ];
3357
3362
  function suggestLabel(relativePath) {
@@ -3360,7 +3365,7 @@ function suggestLabel(relativePath) {
3360
3365
  if (parts.length === 1) {
3361
3366
  return "root";
3362
3367
  }
3363
- return parts[parts.length - 2];
3368
+ return parts[parts.length - 2] ?? "root";
3364
3369
  }
3365
3370
  async function scanDirectoryRecursive(directory, fs, rootDir, options, currentDepth = 0, gitignorePatterns = null) {
3366
3371
  const detected = [];
@@ -3426,12 +3431,12 @@ function filterRedundantPackageJson(manifests) {
3426
3431
  if (!dirToManifests.has(dir)) {
3427
3432
  dirToManifests.set(dir, []);
3428
3433
  }
3429
- dirToManifests.get(dir).push(manifest);
3434
+ dirToManifests.get(dir)?.push(manifest);
3430
3435
  }
3431
3436
  const filtered = [];
3432
- for (const [dir, dirManifests] of dirToManifests.entries()) {
3437
+ for (const [_dir, dirManifests] of dirToManifests.entries()) {
3433
3438
  const hasLockFile = dirManifests.some((m) => m.filename === "package-lock.json");
3434
- const hasPackageJson = dirManifests.some((m) => m.filename === "package.json");
3439
+ const _hasPackageJson = dirManifests.some((m) => m.filename === "package.json");
3435
3440
  for (const manifest of dirManifests) {
3436
3441
  if (manifest.filename === "package.json" && hasLockFile) {
3437
3442
  continue;
@@ -4295,9 +4300,9 @@ Project already configured: ${highlight(existingConfig.config.project, useColors
4295
4300
  setupProject = false;
4296
4301
  } else {
4297
4302
  console.log(`
4298
- ` + "=".repeat(50));
4303
+ ${"=".repeat(50)}`);
4299
4304
  console.log("Project Configuration Setup");
4300
- console.log("=".repeat(50) + `
4305
+ console.log(`${"=".repeat(50)}
4301
4306
  `);
4302
4307
  await projectInit({}, {
4303
4308
  projectService: deps.projectService,
@@ -4318,9 +4323,9 @@ ${highlight("✓", useColors)} Project setup complete!
4318
4323
  }
4319
4324
  if (aiIntegration === "skill") {
4320
4325
  console.log(`
4321
- ` + "=".repeat(50));
4326
+ ${"=".repeat(50)}`);
4322
4327
  console.log("Skill Setup");
4323
- console.log("=".repeat(50) + `
4328
+ console.log(`${"=".repeat(50)}
4324
4329
  `);
4325
4330
  await skillInit({
4326
4331
  fileSystemService: deps.fileSystemService,
@@ -4334,9 +4339,9 @@ ${highlight("✓", useColors)} Skill setup complete!
4334
4339
  const currentConfig = await deps.configService.loadProjectConfig();
4335
4340
  const hasProjectNow = currentConfig?.config.project !== undefined;
4336
4341
  console.log(`
4337
- ` + "=".repeat(50));
4342
+ ${"=".repeat(50)}`);
4338
4343
  console.log("MCP Server Setup");
4339
- console.log("=".repeat(50) + `
4344
+ console.log(`${"=".repeat(50)}
4340
4345
  `);
4341
4346
  await mcpInit({
4342
4347
  fileSystemService: deps.fileSystemService,
@@ -4352,7 +4357,7 @@ ${highlight("✓", useColors)} MCP setup complete!
4352
4357
  }
4353
4358
  console.log("=".repeat(50));
4354
4359
  console.log("Setup Complete!");
4355
- console.log("=".repeat(50) + `
4360
+ console.log(`${"=".repeat(50)}
4356
4361
  `);
4357
4362
  if (setupProject) {
4358
4363
  const finalConfig = await deps.configService.loadProjectConfig();
@@ -4393,8 +4398,7 @@ function showCliUsage(useColors) {
4393
4398
  console.log(` ${highlight("pkgseer docs get <pkg>/<page>", useColors)} Fetch doc content`);
4394
4399
  console.log(` ${highlight("pkgseer docs search <query>", useColors)} Search documentation
4395
4400
  `);
4396
- console.log(dim(`All commands support --json for structured output.
4397
- ` + "Tip: Run 'pkgseer quickstart' for a quick reference guide.", useColors));
4401
+ console.log(dim("All commands support --json for structured output.", useColors));
4398
4402
  }
4399
4403
  function registerInitCommand(program) {
4400
4404
  program.command("init").summary("Set up project and AI integration").description(`Set up PkgSeer for your project.
@@ -4463,9 +4467,11 @@ async function loginAction(options, deps) {
4463
4467
  let callback;
4464
4468
  try {
4465
4469
  callback = await Promise.race([serverPromise, timeoutPromise]);
4466
- clearTimeout(timeoutId);
4470
+ if (timeoutId)
4471
+ clearTimeout(timeoutId);
4467
4472
  } catch (error2) {
4468
- clearTimeout(timeoutId);
4473
+ if (timeoutId)
4474
+ clearTimeout(timeoutId);
4469
4475
  if (error2 instanceof Error) {
4470
4476
  console.log(`${error2.message}.
4471
4477
  `);
@@ -4582,12 +4588,13 @@ function toGraphQLRegistry2(registry) {
4582
4588
  const map = {
4583
4589
  npm: "NPM",
4584
4590
  pypi: "PYPI",
4585
- hex: "HEX"
4591
+ hex: "HEX",
4592
+ crates: "CRATES"
4586
4593
  };
4587
4594
  return map[registry.toLowerCase()] || "NPM";
4588
4595
  }
4589
4596
  var schemas = {
4590
- registry: z2.enum(["npm", "pypi", "hex"]).describe("Package registry (npm, pypi, or hex)"),
4597
+ registry: z2.enum(["npm", "pypi", "hex", "crates"]).describe("Package registry (npm, pypi, hex, or crates)"),
4591
4598
  packageName: z2.string().max(255).describe("Name of the package"),
4592
4599
  version: z2.string().max(100).optional().describe("Specific version (defaults to latest)")
4593
4600
  };
@@ -4630,7 +4637,7 @@ function notFoundError(packageName, registry) {
4630
4637
 
4631
4638
  // src/tools/compare-packages.ts
4632
4639
  var packageInputSchema = z3.object({
4633
- registry: z3.enum(["npm", "pypi", "hex"]),
4640
+ registry: z3.enum(["npm", "pypi", "hex", "crates"]),
4634
4641
  name: z3.string().max(255),
4635
4642
  version: z3.string().max(100).optional()
4636
4643
  });
@@ -4640,7 +4647,7 @@ var argsSchema = {
4640
4647
  function createComparePackagesTool(pkgseerService) {
4641
4648
  return {
4642
4649
  name: "compare_packages",
4643
- description: "Compare 2-10 packages side-by-side. Use this when evaluating alternatives (e.g., react vs preact vs solid-js). " + "Returns for each package: quality score, download counts, vulnerability count, license, and latest version. " + "Supports cross-registry comparison (npm, pypi, hex). " + 'Format: [{"registry":"npm","name":"lodash"},{"registry":"npm","name":"underscore"}]',
4650
+ description: "Compare 2-10 packages side-by-side. Use this when evaluating alternatives (e.g., react vs preact vs solid-js). " + "Returns for each package: quality score, download counts, vulnerability count, license, and latest version. " + "Supports cross-registry comparison (npm, pypi, hex, crates). " + 'Format: [{"registry":"npm","name":"lodash"},{"registry":"npm","name":"underscore"}]',
4644
4651
  schema: argsSchema,
4645
4652
  handler: async ({ packages }, _extra) => {
4646
4653
  return withErrorHandling("compare packages", async () => {
@@ -5173,7 +5180,7 @@ function showMcpSetupInstructions(deps) {
5173
5180
  console.log(` ${highlight(`${deps.baseUrl}/docs/mcp-server`, useColors)}
5174
5181
  `);
5175
5182
  console.log("Alternative: Use CLI directly (no MCP setup needed)");
5176
- console.log(` ${highlight("pkgseer quickstart", useColors)}`);
5183
+ console.log(` ${highlight("pkgseer pkg info <package>", useColors)}`);
5177
5184
  }
5178
5185
  function registerMcpCommand(program) {
5179
5186
  const mcpCommand = program.command("mcp").summary("Show setup instructions or start MCP server").description(`Start the Model Context Protocol (MCP) server using STDIO transport.
@@ -5255,10 +5262,10 @@ async function pkgCompareAction(packages, options, deps) {
5255
5262
  if (options.json) {
5256
5263
  const pkgs = result.data.comparePackages.packages?.filter((p) => p) ?? [];
5257
5264
  const slim = pkgs.map((p) => ({
5258
- package: `${p.packageName}@${p.version}`,
5259
- quality: p.quality?.score,
5260
- downloads: p.downloadsLastMonth,
5261
- vulnerabilities: p.vulnerabilityCount
5265
+ package: `${p?.packageName}@${p?.version}`,
5266
+ quality: p?.quality?.score,
5267
+ downloads: p?.downloadsLastMonth,
5268
+ vulnerabilities: p?.vulnerabilityCount
5262
5269
  }));
5263
5270
  output(slim, true);
5264
5271
  } else {
@@ -5527,8 +5534,8 @@ async function pkgQualityAction(packageArg, options, deps) {
5527
5534
  score: quality?.overallScore,
5528
5535
  grade: quality?.grade,
5529
5536
  categories: quality?.categories?.filter((c) => c).map((c) => ({
5530
- name: c.category,
5531
- score: c.score
5537
+ name: c?.category,
5538
+ score: c?.score
5532
5539
  }))
5533
5540
  };
5534
5541
  output(slim, true);
@@ -5629,10 +5636,10 @@ async function pkgVulnsAction(packageArg, options, deps) {
5629
5636
  package: `${data.package?.name}@${data.package?.version}`,
5630
5637
  count: data.security?.vulnerabilityCount ?? 0,
5631
5638
  vulnerabilities: vulns.filter((v) => v).map((v) => ({
5632
- id: v.osvId,
5633
- severity: v.severityScore,
5634
- summary: v.summary,
5635
- fixed: v.fixedInVersions
5639
+ id: v?.osvId,
5640
+ severity: v?.severityScore,
5641
+ summary: v?.summary,
5642
+ fixed: v?.fixedInVersions
5636
5643
  }))
5637
5644
  };
5638
5645
  output(slim, true);
@@ -5673,7 +5680,7 @@ function matchManifestsWithConfig(detectedGroups, existingManifests) {
5673
5680
  });
5674
5681
  }
5675
5682
  }
5676
- const labelToFiles = new Map;
5683
+ const _labelToFiles = new Map;
5677
5684
  const labelToConfig = new Map;
5678
5685
  for (const detectedGroup of detectedGroups) {
5679
5686
  for (const manifest of detectedGroup.manifests) {
@@ -5686,13 +5693,14 @@ function matchManifestsWithConfig(detectedGroups, existingManifests) {
5686
5693
  label = existingConfig?.label ?? detectedGroup.label;
5687
5694
  }
5688
5695
  const allowMixDeps = existingConfig?.allow_mix_deps;
5689
- if (!labelToConfig.has(label)) {
5690
- labelToConfig.set(label, {
5696
+ let config = labelToConfig.get(label);
5697
+ if (!config) {
5698
+ config = {
5691
5699
  files: new Set,
5692
5700
  allow_mix_deps: allowMixDeps
5693
- });
5701
+ };
5702
+ labelToConfig.set(label, config);
5694
5703
  }
5695
- const config = labelToConfig.get(label);
5696
5704
  config.files.add(manifest.relativePath);
5697
5705
  if (allowMixDeps) {
5698
5706
  config.allow_mix_deps = true;
@@ -5729,7 +5737,7 @@ function matchManifestsWithConfig(detectedGroups, existingManifests) {
5729
5737
  });
5730
5738
  }
5731
5739
  async function projectDetectAction(options, deps) {
5732
- const { configService, fileSystemService, promptService, shellService } = deps;
5740
+ const { configService, fileSystemService, promptService } = deps;
5733
5741
  const projectConfig = await configService.loadProjectConfig();
5734
5742
  if (!projectConfig?.config.project) {
5735
5743
  console.error(`✗ No project is configured in pkgseer.yml`);
@@ -5786,7 +5794,7 @@ Suggested configuration:`);
5786
5794
  console.log(`${prefix}${file}`);
5787
5795
  }
5788
5796
  }
5789
- const hasHexManifests = detectedGroups.some((group) => group.manifests.some((m) => m.type === "hex"));
5797
+ const _hasHexManifests = detectedGroups.some((group) => group.manifests.some((m) => m.type === "hex"));
5790
5798
  const hasHexInSuggested = suggestedManifests.some((g) => g.files.some((f) => f.endsWith("mix.exs") || f.endsWith("mix.lock")));
5791
5799
  let allowMixDeps = false;
5792
5800
  if (hasHexInSuggested) {
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  version
3
- } from "./shared/chunk-48mwa8wt.js";
3
+ } from "./shared/chunk-drz16bhv.js";
4
4
  export {
5
5
  version
6
6
  };
@@ -1,4 +1,4 @@
1
1
  // package.json
2
- var version = "0.2.4";
2
+ var version = "0.2.5";
3
3
 
4
4
  export { version };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pkgseer/cli",
3
3
  "description": "CLI companion for PkgSeer - package intelligence for developers and AI assistants",
4
- "version": "0.2.4",
4
+ "version": "0.2.5",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",