Skip to content

ctx7 skills suggest does not discover dependencies in pnpm monorepo subpackages #1860

@JoeIaquinto

Description

@JoeIaquinto

Summary

ctx7 skills suggest only reads the root package.json for dependencies. In a pnpm monorepo, most (or all) production dependencies live in workspace subpackages under packages/ or apps/, not the root. The root package.json typically only contains devDependencies for tooling (turbo, biome, typescript, etc.).

Root Cause

In ctx7@0.3.0, the detectProjectDependencies function calls parsePackageJson(cwd) which only reads the single package.json in the current working directory:

// ctx7@0.3.0 dist/index.js
async function parsePackageJson(cwd) {
  const content = await readFileOrNull(join(cwd, "package.json"));
  if (!content) return [];
  const pkg = JSON.parse(content);
  const names = new Set();
  for (const key of Object.keys(pkg.dependencies || {})) {
    if (!isSkippedLocally(key)) names.add(key);
  }
  for (const key of Object.keys(pkg.devDependencies || {})) {
    if (!isSkippedLocally(key)) names.add(key);
  }
  return [...names];
}

async function detectProjectDependencies(cwd) {
  const results = await Promise.all([
    parsePackageJson(cwd),
    parseRequirementsTxt(cwd),
    parsePyprojectToml(cwd),
  ]);
  return [...new Set(results.flat())];
}

No workspace detection, no recursive scanning, no lockfile parsing.

Verified Reproduction

Tested with ctx7@0.3.0 on macOS, pnpm 10.7.0, Node 22.x.

1. Set up the monorepo

mkdir ctx7-repro && cd ctx7-repro

Root package.json — only devDeps:

{
  "name": "ctx7-repro",
  "private": true,
  "devDependencies": {
    "turbo": "^2.0.0",
    "typescript": "^5.7.0"
  }
}

pnpm-workspace.yaml — with catalog:

packages:
  - "packages/*"
  - "apps/*"

catalog:
  zod: "^3.24.0"
  react: "^19.0.0"

packages/api/package.json:

{
  "name": "@myapp/api",
  "version": "0.0.1",
  "dependencies": {
    "zod": "catalog:",
    "@orpc/server": "^1.0.0",
    "drizzle-orm": "^0.38.0"
  }
}

apps/web/package.json:

{
  "name": "@myapp/web",
  "version": "0.0.1",
  "dependencies": {
    "react": "catalog:",
    "@tanstack/react-query": "^5.0.0",
    "@tanstack/react-router": "^1.0.0"
  }
}

packages/db/package.json:

{
  "name": "@myapp/db",
  "version": "0.0.1",
  "dependencies": {
    "drizzle-orm": "^0.38.0"
  },
  "devDependencies": {
    "drizzle-kit": "^0.30.0"
  }
}

2. Install and run

pnpm install
npx ctx7 skills suggest   # or: bunx ctx7 skills suggest

3. Results

From monorepo root — only finds 2 deps (turbo, typescript), no skills:

✔ Found 2 dependencies
⚠ No matching skills found for your dependencies

From packages/api/ — finds 3 deps, suggests a skill:

✔ Found 3 dependencies
✔ Found 1 relevant skill(s)

From apps/web/ — finds 3 deps, suggests 3 skills:

✔ Found 3 dependencies
✔ Found 3 relevant skill(s)

The tool works per-subpackage but not from the monorepo root, which is where developers typically run CLI tools.

Directory Tree

ctx7-repro/
├── package.json              ← only devDeps (turbo, typescript) — this is all ctx7 sees
├── pnpm-workspace.yaml       ← workspace + catalog definitions (ignored)
├── pnpm-lock.yaml            ← full resolved dependency graph (ignored)
├── apps/
│   └── web/
│       └── package.json      ← react, @tanstack/react-query, @tanstack/react-router
├── packages/
│   ├── api/
│   │   └── package.json      ← zod, @orpc/server, drizzle-orm
│   └── db/
│       └── package.json      ← drizzle-orm, drizzle-kit
└── node_modules/

Suggested Fix

Detect pnpm/npm/yarn workspaces and aggregate dependencies. For pnpm specifically, pnpm ls --json --recursive --depth 0 returns every dependency across all workspace packages with catalog versions properly resolved:

[
  { "name": "ctx7-repro", "devDependencies": { "turbo": { "version": "2.8.9" }, "typescript": { "version": "5.9.3" } } },
  { "name": "@myapp/web", "dependencies": { "react": { "version": "19.2.4" }, "@tanstack/react-query": { "version": "5.90.21" }, "@tanstack/react-router": { "version": "1.160.0" } } },
  { "name": "@myapp/api", "dependencies": { "zod": { "version": "3.25.76" }, "@orpc/server": { "version": "1.13.5" }, "drizzle-orm": { "version": "0.38.4" } } },
  { "name": "@myapp/db", "dependencies": { "drizzle-orm": { "version": "0.38.4" } }, "devDependencies": { "drizzle-kit": { "version": "0.30.6" } } }
]

Alternatively, a simpler file-based approach:

  1. Detect pnpm-workspace.yaml (pnpm), workspaces field in package.json (npm/yarn)
  2. Glob for package.json files matching workspace patterns
  3. Aggregate dependencies and devDependencies across all matched files

Environment

  • ctx7: 0.3.0
  • pnpm: 10.7.0
  • Node.js: 22.x
  • OS: macOS 24.6.0 (Sequoia)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions