Skip to content

Commit a894363

Browse files
authored
Merge pull request #10 from ivangrynenko/feature/agents-md
feat: add AGENTS.md and installer-generated AGENTS.md
2 parents fb05238 + a1e4d20 commit a894363

File tree

2 files changed

+230
-1
lines changed

2 files changed

+230
-1
lines changed

AGENTS.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Cursor Agents Guide (Using Cursor Rules)
2+
3+
This document explains how to use the rules in this repository with Cursor and serves as a single entry point that references the existing rule files. It avoids duplication by linking directly to the `.cursor/rules/*.mdc` sources.
4+
5+
If you installed these rules via the installer, a project‑local AGENTS.md can be generated that lists only the rules you chose. By default, the installer writes AGENTS.md if absent; it overwrites only when you pass `--yes`.
6+
7+
## How To Use With Cursor
8+
- Open your project in Cursor. Rules under `.cursor/rules` are discovered automatically by Cursor.
9+
- Keep this AGENTS.md handy as your quick index to the rule set.
10+
- For installation methods and advanced options, see `README.md`.
11+
12+
## Installation Options
13+
For full installation details and examples, see `README.md`.
14+
- Core rules only: `--core`
15+
- Web stack (includes core): `--web-stack` or `--ws`
16+
- Python (includes core): `--python`
17+
- JavaScript security (includes core): `--javascript`
18+
- All rules: `--all`
19+
- Tag-based selection: `--tags "<expression>"` or `--tag-preset <name>`
20+
- Ignore files control: `--ignore-files yes|no|ask`
21+
22+
Tag taxonomy is documented in `TAG_STANDARDS.md`.
23+
24+
## Rule Bundles (Source of Truth)
25+
Below are the rule bundles and their rule files. Each item links directly to the authoritative file under `.cursor/rules/`.
26+
27+
### Core
28+
- [.cursor/rules/cursor-rules.mdc](.cursor/rules/cursor-rules.mdc)
29+
- [.cursor/rules/git-commit-standards.mdc](.cursor/rules/git-commit-standards.mdc)
30+
- [.cursor/rules/github-actions-standards.mdc](.cursor/rules/github-actions-standards.mdc)
31+
- [.cursor/rules/improve-cursorrules-efficiency.mdc](.cursor/rules/improve-cursorrules-efficiency.mdc)
32+
- [.cursor/rules/pull-request-changelist-instructions.mdc](.cursor/rules/pull-request-changelist-instructions.mdc)
33+
- [.cursor/rules/readme-maintenance-standards.mdc](.cursor/rules/readme-maintenance-standards.mdc)
34+
- [.cursor/rules/testing-guidelines.mdc](.cursor/rules/testing-guidelines.mdc)
35+
36+
### Web Stack
37+
- [.cursor/rules/accessibility-standards.mdc](.cursor/rules/accessibility-standards.mdc)
38+
- [.cursor/rules/api-standards.mdc](.cursor/rules/api-standards.mdc)
39+
- [.cursor/rules/build-optimization.mdc](.cursor/rules/build-optimization.mdc)
40+
- [.cursor/rules/code-generation-standards.mdc](.cursor/rules/code-generation-standards.mdc)
41+
- [.cursor/rules/debugging-standards.mdc](.cursor/rules/debugging-standards.mdc)
42+
- [.cursor/rules/docker-compose-standards.mdc](.cursor/rules/docker-compose-standards.mdc)
43+
- [.cursor/rules/drupal-authentication-failures.mdc](.cursor/rules/drupal-authentication-failures.mdc)
44+
- [.cursor/rules/drupal-broken-access-control.mdc](.cursor/rules/drupal-broken-access-control.mdc)
45+
- [.cursor/rules/drupal-cryptographic-failures.mdc](.cursor/rules/drupal-cryptographic-failures.mdc)
46+
- [.cursor/rules/drupal-database-standards.mdc](.cursor/rules/drupal-database-standards.mdc)
47+
- [.cursor/rules/drupal-file-permissions.mdc](.cursor/rules/drupal-file-permissions.mdc)
48+
- [.cursor/rules/drupal-injection.mdc](.cursor/rules/drupal-injection.mdc)
49+
- [.cursor/rules/drupal-insecure-design.mdc](.cursor/rules/drupal-insecure-design.mdc)
50+
- [.cursor/rules/drupal-integrity-failures.mdc](.cursor/rules/drupal-integrity-failures.mdc)
51+
- [.cursor/rules/drupal-logging-failures.mdc](.cursor/rules/drupal-logging-failures.mdc)
52+
- [.cursor/rules/drupal-security-misconfiguration.mdc](.cursor/rules/drupal-security-misconfiguration.mdc)
53+
- [.cursor/rules/drupal-ssrf.mdc](.cursor/rules/drupal-ssrf.mdc)
54+
- [.cursor/rules/drupal-vulnerable-components.mdc](.cursor/rules/drupal-vulnerable-components.mdc)
55+
- [.cursor/rules/generic_bash_style.mdc](.cursor/rules/generic_bash_style.mdc)
56+
- [.cursor/rules/govcms-saas-project-documentation-creation.mdc](.cursor/rules/govcms-saas-project-documentation-creation.mdc)
57+
- [.cursor/rules/govcms-saas.mdc](.cursor/rules/govcms-saas.mdc)
58+
- [.cursor/rules/javascript-performance.mdc](.cursor/rules/javascript-performance.mdc)
59+
- [.cursor/rules/javascript-standards.mdc](.cursor/rules/javascript-standards.mdc)
60+
- [.cursor/rules/lagoon-docker-compose-standards.mdc](.cursor/rules/lagoon-docker-compose-standards.mdc)
61+
- [.cursor/rules/lagoon-yml-standards.mdc](.cursor/rules/lagoon-yml-standards.mdc)
62+
- [.cursor/rules/multi-agent-coordination.mdc](.cursor/rules/multi-agent-coordination.mdc)
63+
- [.cursor/rules/node-dependencies.mdc](.cursor/rules/node-dependencies.mdc)
64+
- [.cursor/rules/php-drupal-best-practices.mdc](.cursor/rules/php-drupal-best-practices.mdc)
65+
- [.cursor/rules/php-drupal-development-standards.mdc](.cursor/rules/php-drupal-development-standards.mdc)
66+
- [.cursor/rules/project-definition-template.mdc](.cursor/rules/project-definition-template.mdc)
67+
- [.cursor/rules/react-patterns.mdc](.cursor/rules/react-patterns.mdc)
68+
- [.cursor/rules/security-practices.mdc](.cursor/rules/security-practices.mdc)
69+
- [.cursor/rules/secret-detection.mdc](.cursor/rules/secret-detection.mdc)
70+
- [.cursor/rules/tailwind-standards.mdc](.cursor/rules/tailwind-standards.mdc)
71+
- [.cursor/rules/tests-documentation-maintenance.mdc](.cursor/rules/tests-documentation-maintenance.mdc)
72+
- [.cursor/rules/third-party-integration.mdc](.cursor/rules/third-party-integration.mdc)
73+
- [.cursor/rules/vortex-cicd-standards.mdc](.cursor/rules/vortex-cicd-standards.mdc)
74+
- [.cursor/rules/vortex-scaffold-standards.mdc](.cursor/rules/vortex-scaffold-standards.mdc)
75+
- [.cursor/rules/vue-best-practices.mdc](.cursor/rules/vue-best-practices.mdc)
76+
- [.cursor/rules/behat-steps.mdc](.cursor/rules/behat-steps.mdc)
77+
- [.cursor/rules/behat-ai-guide.mdc](.cursor/rules/behat-ai-guide.mdc)
78+
79+
### Python
80+
- [.cursor/rules/python-authentication-failures.mdc](.cursor/rules/python-authentication-failures.mdc)
81+
- [.cursor/rules/python-broken-access-control.mdc](.cursor/rules/python-broken-access-control.mdc)
82+
- [.cursor/rules/python-cryptographic-failures.mdc](.cursor/rules/python-cryptographic-failures.mdc)
83+
- [.cursor/rules/python-injection.mdc](.cursor/rules/python-injection.mdc)
84+
- [.cursor/rules/python-insecure-design.mdc](.cursor/rules/python-insecure-design.mdc)
85+
- [.cursor/rules/python-integrity-failures.mdc](.cursor/rules/python-integrity-failures.mdc)
86+
- [.cursor/rules/python-logging-monitoring-failures.mdc](.cursor/rules/python-logging-monitoring-failures.mdc)
87+
- [.cursor/rules/python-security-misconfiguration.mdc](.cursor/rules/python-security-misconfiguration.mdc)
88+
- [.cursor/rules/python-ssrf.mdc](.cursor/rules/python-ssrf.mdc)
89+
- [.cursor/rules/python-vulnerable-outdated-components.mdc](.cursor/rules/python-vulnerable-outdated-components.mdc)
90+
- [.cursor/rules/security-practices.mdc](.cursor/rules/security-practices.mdc)
91+
92+
### JavaScript Security
93+
- [.cursor/rules/javascript-broken-access-control.mdc](.cursor/rules/javascript-broken-access-control.mdc)
94+
- [.cursor/rules/javascript-cryptographic-failures.mdc](.cursor/rules/javascript-cryptographic-failures.mdc)
95+
- [.cursor/rules/javascript-identification-authentication-failures.mdc](.cursor/rules/javascript-identification-authentication-failures.mdc)
96+
- [.cursor/rules/javascript-injection.mdc](.cursor/rules/javascript-injection.mdc)
97+
- [.cursor/rules/javascript-insecure-design.mdc](.cursor/rules/javascript-insecure-design.mdc)
98+
- [.cursor/rules/javascript-security-logging-monitoring-failures.mdc](.cursor/rules/javascript-security-logging-monitoring-failures.mdc)
99+
- [.cursor/rules/javascript-security-misconfiguration.mdc](.cursor/rules/javascript-security-misconfiguration.mdc)
100+
- [.cursor/rules/javascript-server-side-request-forgery.mdc](.cursor/rules/javascript-server-side-request-forgery.mdc)
101+
- [.cursor/rules/javascript-software-data-integrity-failures.mdc](.cursor/rules/javascript-software-data-integrity-failures.mdc)
102+
- [.cursor/rules/javascript-vulnerable-outdated-components.mdc](.cursor/rules/javascript-vulnerable-outdated-components.mdc)
103+
104+
## Tag-Based Selection
105+
The installer supports tag expressions and presets. Examples:
106+
- `--tags "language:javascript category:security"`
107+
- `--tags "framework:react"`
108+
- `--tags "language:php standard:owasp-top10"`
109+
- `--tag-preset js-owasp`
110+
111+
See `TAG_STANDARDS.md` for the complete tag taxonomy and guidance.
112+
113+
## Updating Or Removing
114+
- To update, re-run the installer with your preferred options (it will copy over updated rules). See `README.md`.
115+
- To remove rules, delete files from `.cursor/rules` and remove any generated `.cursorignore` files if not needed.
116+
117+
## References
118+
- Project README: [README.md](README.md)
119+
- Tag standards: [TAG_STANDARDS.md](TAG_STANDARDS.md)
120+
- All rule sources: `.cursor/rules/*.mdc`

install.php

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,115 @@ function is_valid_source_dir($dir, $rule_files) {
724724
}
725725
}
726726

727+
// Optionally generate a project-local AGENTS.md summarising installed rules.
728+
// Write if absent; overwrite only when --yes was passed.
729+
try {
730+
$project_root = getcwd();
731+
$agents_md_path = $project_root . '/AGENTS.md';
732+
733+
$should_write_agents = !file_exists($agents_md_path) || !empty($options['yes']);
734+
735+
if ($should_write_agents) {
736+
// Prepare bundle definitions for grouping in AGENTS.md
737+
$bundle_map = [
738+
'Core' => $core_rules,
739+
'Web Stack' => $web_stack_rules,
740+
'Python' => $python_rules,
741+
'JavaScript Security' => $javascript_rules,
742+
];
743+
744+
$lines = [];
745+
$lines[] = '# Cursor Agents Guide (Installed Rules)';
746+
$lines[] = '';
747+
$lines[] = 'This file is generated by the installer to index the rules currently installed in this project. It links to the authoritative `.cursor/rules/*.mdc` files.';
748+
$lines[] = '';
749+
750+
// Installation summary
751+
$lines[] = '## Installation Summary';
752+
if ($options['all']) {
753+
$lines[] = '- Installation type: All rules (core, web stack, Python, JavaScript)';
754+
} elseif ($options['web_stack']) {
755+
$lines[] = '- Installation type: Web stack (includes core and JavaScript security)';
756+
} elseif ($options['python']) {
757+
$lines[] = '- Installation type: Python (includes core)';
758+
} elseif ($options['javascript']) {
759+
$lines[] = '- Installation type: JavaScript security (includes core)';
760+
} elseif ($options['core']) {
761+
$lines[] = '- Installation type: Core only';
762+
} elseif ($options['tags'] || $options['tag-preset']) {
763+
$tag_expression = $options['tags'] ?: (TAG_PRESETS[$options['tag-preset']] ?? '');
764+
$lines[] = '- Installation type: Tag-based selection';
765+
if (!empty($tag_expression)) {
766+
$lines[] = "- Tag expression: `{$tag_expression}`";
767+
}
768+
} else {
769+
$lines[] = '- Installation type: Default (core)';
770+
}
771+
if (($options['tags'] || $options['tag-preset']) && isset($filtered_count)) {
772+
$lines[] = "- Filtered out: {$filtered_count} rules (did not match tags)";
773+
}
774+
$lines[] = '';
775+
$lines[] = 'For installation methods and options, see `README.md`. For tag taxonomy, see `TAG_STANDARDS.md`.';
776+
$lines[] = '';
777+
778+
// Bundles present
779+
$lines[] = '## Installed Bundles';
780+
$any_bundle_listed = false;
781+
foreach ($bundle_map as $bundle_name => $bundle_rules) {
782+
$installed_subset = array_values(array_intersect($rules_to_install, $bundle_rules));
783+
if (count($installed_subset) > 0) {
784+
$lines[] = "- {$bundle_name}";
785+
$any_bundle_listed = true;
786+
}
787+
}
788+
if (!$any_bundle_listed) {
789+
$lines[] = '- Core';
790+
}
791+
$lines[] = '';
792+
793+
// Grouped rule links
794+
$lines[] = '## Installed Rules';
795+
foreach ($bundle_map as $bundle_name => $bundle_rules) {
796+
$installed_subset = array_values(array_intersect($rules_to_install, $bundle_rules));
797+
if (count($installed_subset) === 0) {
798+
continue;
799+
}
800+
$lines[] = "### {$bundle_name}";
801+
foreach ($installed_subset as $rule_file) {
802+
$lines[] = "- [.cursor/rules/{$rule_file}](.cursor/rules/{$rule_file})";
803+
}
804+
$lines[] = '';
805+
}
806+
807+
// Fallback: if some rules were not mapped (shouldn't happen), list them
808+
$all_mapped = array_unique(array_merge(...array_values($bundle_map)));
809+
$unmapped = array_values(array_diff($rules_to_install, $all_mapped));
810+
if (count($unmapped) > 0) {
811+
$lines[] = '### Other';
812+
foreach ($unmapped as $rule_file) {
813+
$lines[] = "- [.cursor/rules/{$rule_file}](.cursor/rules/{$rule_file})";
814+
}
815+
$lines[] = '';
816+
}
817+
818+
$content = implode("\n", $lines) . "\n";
819+
@file_put_contents($agents_md_path, $content);
820+
821+
if ($options['debug']) {
822+
echo "Generated AGENTS.md at: {$agents_md_path}\n";
823+
}
824+
} else {
825+
if ($options['debug']) {
826+
echo "AGENTS.md exists and --yes not set; skipping generation.\n";
827+
}
828+
}
829+
} catch (\Throwable $e) {
830+
// Non-fatal: continue even if AGENTS.md generation fails
831+
if ($options['debug']) {
832+
echo "Warning: Failed to generate AGENTS.md (" . $e->getMessage() . ")\n";
833+
}
834+
}
835+
727836
// Create UPDATE.md file to track version
728837
$cursor_parent_dir = dirname($options['destination']);
729838
$update_file_path = $cursor_parent_dir . '/UPDATE.md';
@@ -1145,4 +1254,4 @@ function parseArguments() {
11451254
}
11461255

11471256
return [$options, $option_count];
1148-
}
1257+
}

0 commit comments

Comments
 (0)