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 +16 -0
- package/README.md +6 -5
- package/package.json +7 -1
- package/src/detect.js +63 -15
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
|
|
57
|
-
|
|
58
|
-
|
|
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.
|
|
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 (
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
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 (
|
|
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 {
|