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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions