agents-md-gen 0.4.2 → 0.5.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,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0
4
+
5
+ - Detect PHP/Composer projects (Laravel/Symfony framework detection,
6
+ PHPUnit, PHPCS).
7
+ - Detect .NET/C# projects via `.csproj`/`.sln` (xUnit/NUnit/MSTest
8
+ detection).
9
+
3
10
  ## 0.4.2
4
11
 
5
12
  - Detect Docker (`Dockerfile`, `docker-compose.yml`/`compose.yml`) and
package/README.md CHANGED
@@ -60,6 +60,8 @@ docker run --rm -v "$PWD":/workdir ghcr.io/peshino2012/agents-md-gen
60
60
  - **Go** — go.mod, golangci-lint
61
61
  - **Ruby** — Bundler, RSpec
62
62
  - **Java/Kotlin** — Maven, Gradle (with wrapper detection)
63
+ - **PHP** — Composer, Laravel/Symfony detection, PHPUnit
64
+ - **.NET/C#** — NuGet, xUnit/NUnit/MSTest detection
63
65
  - **Monorepos** — Turborepo, Nx, Lerna, npm/yarn/pnpm workspaces, listing
64
66
  each detected sub-package
65
67
  - CI (GitHub Actions), license, and top-level project structure
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-md-gen",
3
- "version": "0.4.2",
3
+ "version": "0.5.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
6
  "funding": {
@@ -37,6 +37,11 @@
37
37
  "monorepo",
38
38
  "turborepo",
39
39
  "nx",
40
+ "php",
41
+ "composer",
42
+ "laravel",
43
+ "dotnet",
44
+ "csharp",
40
45
  "cli",
41
46
  "codegen",
42
47
  "developer-tools"
package/src/detect.js CHANGED
@@ -229,6 +229,71 @@ function detectRuby(root) {
229
229
  };
230
230
  }
231
231
 
232
+ function detectPhp(root) {
233
+ const composer = readJson(root, 'composer.json');
234
+ if (!composer) return null;
235
+
236
+ const deps = composer.require || {};
237
+ const devDeps = composer['require-dev'] || {};
238
+ const usesPhpunit = 'phpunit/phpunit' in devDeps || exists(root, 'phpunit.xml') || exists(root, 'phpunit.xml.dist');
239
+ const usesPhpcs = 'squizlabs/php_codesniffer' in devDeps || exists(root, 'phpcs.xml') || exists(root, 'phpcs.xml.dist');
240
+ const scripts = composer.scripts || {};
241
+
242
+ return {
243
+ ecosystem: 'PHP',
244
+ name: composer.name || null,
245
+ description: composer.description || null,
246
+ packageManager: 'composer',
247
+ frameworks: [
248
+ 'laravel/framework' in deps ? 'Laravel' : null,
249
+ 'symfony/framework-bundle' in deps ? 'Symfony' : null,
250
+ ].filter(Boolean),
251
+ testFramework: usesPhpunit ? 'PHPUnit' : null,
252
+ commands: {
253
+ install: 'composer install',
254
+ build: null,
255
+ test: scripts.test ? 'composer test' : (usesPhpunit ? 'vendor/bin/phpunit' : null),
256
+ lint: usesPhpcs ? 'vendor/bin/phpcs' : null,
257
+ dev: null,
258
+ },
259
+ };
260
+ }
261
+
262
+ function detectDotnet(root) {
263
+ let entries;
264
+ try {
265
+ entries = fs.readdirSync(root, { withFileTypes: true });
266
+ } catch {
267
+ return null;
268
+ }
269
+ const files = entries.filter((e) => e.isFile()).map((e) => e.name);
270
+ const sln = files.find((f) => f.endsWith('.sln'));
271
+ const csproj = files.find((f) => f.endsWith('.csproj'));
272
+ if (!sln && !csproj) return null;
273
+
274
+ const projectText = csproj ? (readText(root, csproj) || '') : '';
275
+ const testFramework = /xunit/i.test(projectText) ? 'xUnit'
276
+ : /nunit/i.test(projectText) ? 'NUnit'
277
+ : /Microsoft\.NET\.Test\.Sdk/i.test(projectText) ? 'MSTest'
278
+ : null;
279
+
280
+ return {
281
+ ecosystem: '.NET',
282
+ name: sln ? sln.replace(/\.sln$/, '') : (csproj ? csproj.replace(/\.csproj$/, '') : null),
283
+ description: null,
284
+ packageManager: 'nuget',
285
+ frameworks: [],
286
+ testFramework,
287
+ commands: {
288
+ install: 'dotnet restore',
289
+ build: 'dotnet build',
290
+ test: testFramework ? 'dotnet test' : null,
291
+ lint: 'dotnet format',
292
+ dev: null,
293
+ },
294
+ };
295
+ }
296
+
232
297
  // Excluded so re-running the generator doesn't see its own prior output as
233
298
  // part of the repo's structure - otherwise the file it just wrote would
234
299
  // never match a freshly rendered one, breaking `--check`.
@@ -325,7 +390,7 @@ function detectMonorepo(root) {
325
390
  }
326
391
 
327
392
  function detectProject(root) {
328
- const detectors = [detectNode, detectPython, detectRust, detectGo, detectRuby, detectJava];
393
+ const detectors = [detectNode, detectPython, detectRust, detectGo, detectRuby, detectJava, detectPhp, detectDotnet];
329
394
  const stacks = detectors.map((fn) => fn(root)).filter(Boolean);
330
395
 
331
396
  return {