agents-md-gen 0.10.0 → 0.11.0

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
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.0
4
+
5
+ - Fix: Bun projects using the text `bun.lock` (the default since Bun 1.2)
6
+ were reported as npm. Both `bun.lock` and `bun.lockb` count now.
7
+ - Honor corepack's `packageManager` field in package.json over lockfiles.
8
+ - More JS frameworks: Remix, Expo, React Native, Nuxt, SvelteKit, Astro,
9
+ Angular, Hono, Electron; meta-frameworks replace the library they wrap
10
+ (Nuxt instead of Vue, SvelteKit instead of Svelte). Playwright as a test
11
+ runner.
12
+ - Detect Deno projects (`deno.json`/`deno.jsonc`, its tasks, Fresh/Hono).
13
+ - A lone `Pipfile` (no lock yet) is detected as a pipenv Python project.
14
+ - `homepage` points at the public distribution repo; it used to fall back
15
+ to the private source repo, which 404s for visitors.
16
+ - The README's "real output" example is now checked against the actual
17
+ CLI output by the test suite, so it can't drift again.
18
+
3
19
  ## 0.10.0
4
20
 
5
21
  - Detect web frameworks in ecosystems that always reported none:
package/README.md CHANGED
@@ -53,9 +53,12 @@ docker run --rm -v "$PWD":/workdir ghcr.io/peshino2012/agents-md-gen
53
53
 
54
54
  ## What it detects
55
55
 
56
- - **Node.js / TypeScript** — package manager (npm/yarn/pnpm/bun), framework
57
- (React, Next.js, Vue, Svelte, Express, Fastify, NestJS), test runner
58
- (Jest, Vitest, Mocha, Ava, node:test)
56
+ - **Node.js / TypeScript** — package manager (npm/yarn/pnpm/bun, honoring the
57
+ `packageManager` field), framework (Next.js, Remix, React, Expo/React
58
+ Native, Nuxt, Vue, SvelteKit, Svelte, Astro, Angular, Express, Fastify,
59
+ NestJS, Hono, Electron), test runner (Vitest, Jest, Mocha, Ava,
60
+ node:test, Playwright)
61
+ - **Deno** — `deno.json`/`deno.jsonc` tasks, Fresh/Hono
59
62
  - **Python** — package manager (pip/poetry/uv/pipenv), Django/FastAPI/Flask,
60
63
  pytest or the Django test runner, ruff
61
64
  - **Rust** — Cargo, workspaces, Axum/Actix Web/Rocket/Tauri, clippy
@@ -141,7 +144,6 @@ this package's own repo:
141
144
 
142
145
  ## Structure
143
146
 
144
- - `.github/` — GitHub config (CI, templates)
145
147
  - `CHANGELOG.md`
146
148
  - `Dockerfile`
147
149
  - `LICENSE`
@@ -153,7 +155,6 @@ this package's own repo:
153
155
 
154
156
  ## Notes
155
157
 
156
- - CI: GitHub Actions (test.yml)
157
158
  - License: MIT
158
159
  - Docker: Dockerfile
159
160
  ````
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "agents-md-gen",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Generate a solid AGENTS.md / CLAUDE.md for any repo by detecting its stack, commands, and structure",
5
5
  "license": "MIT",
6
+ "homepage": "https://github.com/Peshino2012/homebrew-tap#readme",
6
7
  "funding": {
7
8
  "type": "individual",
8
9
  "url": "https://www.npmjs.com/package/agents-md-gen"
@@ -58,6 +59,11 @@
58
59
  "fastapi",
59
60
  "flask",
60
61
  "rails",
62
+ "deno",
63
+ "bun",
64
+ "nuxt",
65
+ "sveltekit",
66
+ "astro",
61
67
  "cli",
62
68
  "codegen",
63
69
  "developer-tools"
package/src/detect.js CHANGED
@@ -31,30 +31,49 @@ function detectNode(root) {
31
31
  const pkg = readJson(root, 'package.json');
32
32
  if (!pkg) return null;
33
33
 
34
+ // corepack's `packageManager` field ("pnpm@9.12.0") is explicit, so it wins
35
+ // over lockfile sniffing -- and it's the only signal when no lockfile is
36
+ // committed.
37
+ const declared = typeof pkg.packageManager === 'string' ? pkg.packageManager.split('@')[0] : null;
34
38
  let packageManager = 'npm';
35
- if (exists(root, 'pnpm-lock.yaml')) packageManager = 'pnpm';
39
+ if (['npm', 'pnpm', 'yarn', 'bun'].includes(declared)) packageManager = declared;
40
+ else if (exists(root, 'pnpm-lock.yaml')) packageManager = 'pnpm';
36
41
  else if (exists(root, 'yarn.lock')) packageManager = 'yarn';
37
- else if (exists(root, 'bun.lockb')) packageManager = 'bun';
42
+ else if (exists(root, 'bun.lock') || exists(root, 'bun.lockb')) packageManager = 'bun';
38
43
 
39
44
  const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
40
45
  const has = (name) => Object.prototype.hasOwnProperty.call(deps, name);
41
46
 
42
- const frameworks = [];
43
- if (has('next')) frameworks.push('Next.js');
44
- if (has('react') && !has('next')) frameworks.push('React');
45
- if (has('vue')) frameworks.push('Vue');
46
- if (has('svelte')) frameworks.push('Svelte');
47
- if (has('express')) frameworks.push('Express');
48
- if (has('fastify')) frameworks.push('Fastify');
49
- if (has('@nestjs/core')) frameworks.push('NestJS');
50
- if (has('vite')) frameworks.push('Vite');
51
- if (has('typescript')) frameworks.push('TypeScript');
47
+ // Meta-frameworks are listed instead of the library they're built on
48
+ // (Nuxt, not Vue; SvelteKit, not Svelte).
49
+ const isRemix = has('@remix-run/react') || has('@remix-run/node');
50
+ const frameworks = [
51
+ has('next') && 'Next.js',
52
+ isRemix && 'Remix',
53
+ has('expo') && 'Expo',
54
+ has('react-native') && !has('expo') && 'React Native',
55
+ has('react') && !has('next') && !isRemix && !has('react-native') && 'React',
56
+ has('nuxt') && 'Nuxt',
57
+ has('vue') && !has('nuxt') && 'Vue',
58
+ has('@sveltejs/kit') && 'SvelteKit',
59
+ has('svelte') && !has('@sveltejs/kit') && 'Svelte',
60
+ has('astro') && 'Astro',
61
+ has('@angular/core') && 'Angular',
62
+ has('express') && 'Express',
63
+ has('fastify') && 'Fastify',
64
+ has('@nestjs/core') && 'NestJS',
65
+ has('hono') && 'Hono',
66
+ has('electron') && 'Electron',
67
+ has('vite') && 'Vite',
68
+ has('typescript') && 'TypeScript',
69
+ ].filter(Boolean);
52
70
 
53
71
  const testFramework = has('vitest') ? 'vitest'
54
72
  : has('jest') ? 'jest'
55
73
  : has('mocha') ? 'mocha'
56
74
  : has('ava') ? 'ava'
57
75
  : (pkg.scripts && pkg.scripts.test && pkg.scripts.test.includes('node --test')) ? 'node:test'
76
+ : has('@playwright/test') ? 'playwright'
58
77
  : null;
59
78
 
60
79
  const run = (script) => (pkg.scripts && pkg.scripts[script]) ? `${packageManager} run ${script}` : null;
@@ -78,16 +97,45 @@ function detectNode(root) {
78
97
  };
79
98
  }
80
99
 
100
+ function detectDeno(root) {
101
+ const file = ['deno.json', 'deno.jsonc'].find((f) => exists(root, f));
102
+ if (!file) return null;
103
+ const config = readJsonWithComments(root, file) || {};
104
+ const tasks = config.tasks || {};
105
+ const task = (name) => (tasks[name] ? `deno task ${name}` : null);
106
+ const text = readText(root, file) || '';
107
+
108
+ return {
109
+ ecosystem: 'Deno',
110
+ name: config.name || null,
111
+ description: null,
112
+ packageManager: 'deno',
113
+ frameworks: [
114
+ /\$fresh\/|@fresh\/core/.test(text) && 'Fresh',
115
+ /\bhono\b/.test(text) && 'Hono',
116
+ ].filter(Boolean),
117
+ testFramework: 'deno test',
118
+ commands: {
119
+ install: null,
120
+ build: task('build'),
121
+ test: task('test') || 'deno test',
122
+ lint: task('lint') || 'deno lint',
123
+ dev: task('dev') || task('start'),
124
+ },
125
+ };
126
+ }
127
+
81
128
  function detectPython(root) {
82
129
  const hasPyproject = exists(root, 'pyproject.toml');
83
130
  const hasRequirements = exists(root, 'requirements.txt');
84
131
  const hasSetupPy = exists(root, 'setup.py');
85
- if (!hasPyproject && !hasRequirements && !hasSetupPy) return null;
132
+ const hasPipfile = exists(root, 'Pipfile');
133
+ if (!hasPyproject && !hasRequirements && !hasSetupPy && !hasPipfile) return null;
86
134
 
87
135
  let packageManager = 'pip';
88
136
  if (exists(root, 'poetry.lock')) packageManager = 'poetry';
89
137
  else if (exists(root, 'uv.lock')) packageManager = 'uv';
90
- else if (exists(root, 'Pipfile.lock')) packageManager = 'pipenv';
138
+ else if (hasPipfile) packageManager = 'pipenv';
91
139
 
92
140
  const pyproject = readText(root, 'pyproject.toml') || '';
93
141
  const usesPytest = exists(root, 'pytest.ini') || exists(root, 'conftest.py') || /pytest/.test(pyproject);
@@ -643,7 +691,7 @@ function detectMonorepo(root) {
643
691
  }
644
692
 
645
693
  function detectProject(root) {
646
- const detectors = [detectNode, detectPython, detectRust, detectGo, detectRuby, detectJava, detectPhp, detectDotnet, detectSwift, detectDart, detectElixir, detectCpp, detectHaskell, detectScala, detectZig, detectJulia];
694
+ const detectors = [detectNode, detectDeno, detectPython, detectRust, detectGo, detectRuby, detectJava, detectPhp, detectDotnet, detectSwift, detectDart, detectElixir, detectCpp, detectHaskell, detectScala, detectZig, detectJulia];
647
695
  const stacks = detectors.map((fn) => fn(root)).filter(Boolean);
648
696
 
649
697
  return {