compose-agentsmd 3.2.4 → 3.2.6

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/README.md CHANGED
@@ -68,7 +68,7 @@ compose-agentsmd edit-rules
68
68
  compose-agentsmd apply-rules
69
69
  ```
70
70
 
71
- `edit-rules` clones the GitHub source into the workspace (or reuses it). `apply-rules` pushes the workspace (if clean) and regenerates `AGENTS.md` by refreshing the cache. If your `source` is a local path, `edit-rules` will just print that path and `apply-rules` will skip the push.
71
+ `edit-rules` clones the GitHub source into the workspace (or reuses it), then prints the workspace path, rules directory, and next steps. `apply-rules` pushes the workspace (if clean) and regenerates `AGENTS.md` by refreshing the cache. If your `source` is a local path, `edit-rules` points to the local workspace and `apply-rules` skips the push.
72
72
 
73
73
  ## Project ruleset format
74
74
 
@@ -44,6 +44,14 @@ const parseArgs = (argv) => {
44
44
  args.verbose = true;
45
45
  continue;
46
46
  }
47
+ if (arg === "--quiet" || arg === "-q") {
48
+ args.quiet = true;
49
+ continue;
50
+ }
51
+ if (arg === "--json") {
52
+ args.json = true;
53
+ continue;
54
+ }
47
55
  if (arg === "--root") {
48
56
  const value = readValueArg(remaining, i, "--root");
49
57
  args.root = value;
@@ -536,8 +544,10 @@ const composeRuleset = (rulesetPath, rootDir, options) => {
536
544
  const lintHeader = "<!-- markdownlint-disable MD025 -->";
537
545
  const toolRules = normalizeTrailingWhitespace(TOOL_RULES);
538
546
  const output = `${lintHeader}\n${[toolRules, ...parts].join("\n\n")}\n`;
539
- fs.mkdirSync(path.dirname(outputPath), { recursive: true });
540
- fs.writeFileSync(outputPath, output, "utf8");
547
+ if (!options.dryRun) {
548
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
549
+ fs.writeFileSync(outputPath, output, "utf8");
550
+ }
541
551
  return normalizePath(path.relative(rootDir, outputPath));
542
552
  };
543
553
  const LOCAL_RULES_TEMPLATE = "# Local Rules\n\n- Add project-specific instructions here.\n";
@@ -641,9 +651,22 @@ const initProject = async (args, rootDir, rulesetName) => {
641
651
  plan.push({ action: "create", path: outputPath });
642
652
  }
643
653
  }
644
- process.stdout.write(formatPlan(plan, rootDir));
654
+ if (!args.quiet && !args.json) {
655
+ process.stdout.write(formatPlan(plan, rootDir));
656
+ }
645
657
  if (args.dryRun) {
646
- process.stdout.write("Dry run: no changes made.\n");
658
+ if (args.json) {
659
+ process.stdout.write(JSON.stringify({
660
+ dryRun: true,
661
+ plan: plan.map((item) => ({
662
+ action: item.action,
663
+ path: normalizePath(path.relative(rootDir, item.path))
664
+ }))
665
+ }, null, 2) + "\n");
666
+ }
667
+ else if (!args.quiet) {
668
+ process.stdout.write("Dry run: no changes made.\n");
669
+ }
647
670
  return;
648
671
  }
649
672
  await confirmInit(args);
@@ -653,15 +676,28 @@ const initProject = async (args, rootDir, rulesetName) => {
653
676
  fs.mkdirSync(path.dirname(extraPath), { recursive: true });
654
677
  fs.writeFileSync(extraPath, LOCAL_RULES_TEMPLATE, "utf8");
655
678
  }
656
- process.stdout.write(`Initialized ruleset:\n- ${normalizePath(path.relative(rootDir, rulesetPath))}\n`);
657
- if (extraToWrite.length > 0) {
658
- process.stdout.write(`Initialized local rules:\n${extraToWrite
659
- .map((filePath) => `- ${normalizePath(path.relative(rootDir, filePath))}`)
660
- .join("\n")}\n`);
661
- }
679
+ let composedOutput;
662
680
  if (args.compose) {
663
- const output = composeRuleset(rulesetPath, rootDir, { refresh: args.refresh ?? false });
664
- process.stdout.write(`Composed AGENTS.md:\n- ${output}\n`);
681
+ composedOutput = composeRuleset(rulesetPath, rootDir, { refresh: args.refresh ?? false });
682
+ }
683
+ if (args.json) {
684
+ process.stdout.write(JSON.stringify({
685
+ initialized: [normalizePath(path.relative(rootDir, rulesetPath))],
686
+ localRules: extraToWrite.map((filePath) => normalizePath(path.relative(rootDir, filePath))),
687
+ composed: composedOutput ? [composedOutput] : [],
688
+ dryRun: false
689
+ }, null, 2) + "\n");
690
+ }
691
+ else if (!args.quiet) {
692
+ process.stdout.write(`Initialized ruleset:\n- ${normalizePath(path.relative(rootDir, rulesetPath))}\n`);
693
+ if (extraToWrite.length > 0) {
694
+ process.stdout.write(`Initialized local rules:\n${extraToWrite
695
+ .map((filePath) => `- ${normalizePath(path.relative(rootDir, filePath))}`)
696
+ .join("\n")}\n`);
697
+ }
698
+ if (composedOutput) {
699
+ process.stdout.write(`Composed AGENTS.md:\n- ${composedOutput}\n`);
700
+ }
665
701
  }
666
702
  };
667
703
  const getRulesetFiles = (rootDir, specificRuleset, rulesetName) => {
@@ -719,7 +755,17 @@ const main = async () => {
719
755
  if (ruleset.source.startsWith("github:")) {
720
756
  workspaceRoot = ensureWorkspaceForGithubSource(ruleset.source);
721
757
  }
722
- process.stdout.write(`Rules workspace: ${workspaceRoot}\n`);
758
+ const rulesDirectory = ruleset.source.startsWith("github:")
759
+ ? path.join(workspaceRoot, "rules")
760
+ : resolveLocalRulesRoot(rulesetDir, ruleset.source);
761
+ process.stdout.write([
762
+ `Rules workspace: ${workspaceRoot}`,
763
+ `Rules directory: ${rulesDirectory}`,
764
+ "Next steps:",
765
+ `- Edit rule files under: ${rulesDirectory}`,
766
+ "- If this source is GitHub, commit and push the workspace changes before apply-rules.",
767
+ "- Run compose-agentsmd apply-rules from your project root to apply updates and regenerate AGENTS.md."
768
+ ].join("\n") + "\n");
723
769
  return;
724
770
  }
725
771
  if (command === "init") {
@@ -731,8 +777,13 @@ const main = async () => {
731
777
  const rulesetDir = path.dirname(rulesetPath);
732
778
  const ruleset = readProjectRuleset(rulesetPath);
733
779
  applyRulesFromWorkspace(rulesetDir, ruleset.source);
734
- const output = composeRuleset(rulesetPath, rootDir, { refresh: true });
735
- process.stdout.write(`Composed AGENTS.md:\n- ${output}\n`);
780
+ const output = composeRuleset(rulesetPath, rootDir, { refresh: true, dryRun: args.dryRun });
781
+ if (args.json) {
782
+ process.stdout.write(JSON.stringify({ composed: [output], dryRun: !!args.dryRun }, null, 2) + "\n");
783
+ }
784
+ else if (!args.quiet) {
785
+ process.stdout.write(`Composed AGENTS.md:\n- ${output}\n`);
786
+ }
736
787
  return;
737
788
  }
738
789
  if (rulesetFiles.length === 0) {
@@ -741,8 +792,13 @@ const main = async () => {
741
792
  }
742
793
  const outputs = rulesetFiles
743
794
  .sort()
744
- .map((rulesetPath) => composeRuleset(rulesetPath, rootDir, { refresh: args.refresh }));
745
- process.stdout.write(`Composed AGENTS.md:\n${outputs.map((file) => `- ${file}`).join("\n")}\n`);
795
+ .map((rulesetPath) => composeRuleset(rulesetPath, rootDir, { refresh: args.refresh, dryRun: args.dryRun }));
796
+ if (args.json) {
797
+ process.stdout.write(JSON.stringify({ composed: outputs, dryRun: !!args.dryRun }, null, 2) + "\n");
798
+ }
799
+ else if (!args.quiet) {
800
+ process.stdout.write(`Composed AGENTS.md:\n${outputs.map((file) => `- ${file}`).join("\n")}\n`);
801
+ }
746
802
  };
747
803
  const run = async () => {
748
804
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compose-agentsmd",
3
- "version": "3.2.4",
3
+ "version": "3.2.6",
4
4
  "description": "CLI tools for composing per-project AGENTS.md files from modular rule sets",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,7 +1,12 @@
1
1
  # Tool Rules (compose-agentsmd)
2
2
  - Before starting any work, run `compose-agentsmd` from the project root.
3
+ - `compose-agentsmd` intentionally regenerates `AGENTS.md`; any resulting `AGENTS.md` diff is expected and must not be treated as an unexpected external change.
4
+ - If `compose-agentsmd` is not available, install it via npm: `npm install -g compose-agentsmd`.
3
5
  - To update shared rules, run `compose-agentsmd edit-rules`, edit the workspace rules, then run `compose-agentsmd apply-rules`.
6
+ - `compose-agentsmd apply-rules` pushes the rules workspace when `source` is GitHub (if the workspace is clean), then regenerates `AGENTS.md` with refreshed rules.
4
7
  - Do not edit `AGENTS.md` directly; update the source rules and regenerate.
8
+ - `tools/tool-rules.md` is the shared rule source for all repositories that use compose-agentsmd.
9
+ - Before applying any rule updates, present the planned changes first (prefer a colorized diff-style preview), ask for explicit approval, then make the edits.
5
10
  - These tool rules live in tools/tool-rules.md in the compose-agentsmd repository; do not duplicate them in global rule modules.
6
11
  - When updating rules, include a colorized diff-style summary in the final response. Use `git diff --stat` first, then include the raw ANSI-colored output of `git diff --color=always` (no sanitizing or reformatting), and limit the output to the rule files that changed.
7
12
  - Also provide a short, copy-pasteable command the user can run to view the diff in the same format. Use absolute paths so it works regardless of the current working directory, and scope it to the changed rule files.
package/tools/usage.txt CHANGED
@@ -1,9 +1,11 @@
1
- Usage: compose-agentsmd [edit-rules|apply-rules|init] [--root <path>] [--ruleset <path>] [--ruleset-name <name>] [--source <source>] [--domains <list>] [--extra <list>] [--output <file>] [--no-domains] [--no-extra] [--no-global] [--compose] [--dry-run] [--yes] [--force] [--refresh] [--clear-cache] [--version|-V] [--verbose|-v] [--help|-h]
1
+ Usage: compose-agentsmd [edit-rules|apply-rules|init] [--root <path>] [--ruleset <path>] [--ruleset-name <name>] [--source <source>] [--domains <list>] [--extra <list>] [--output <file>] [--no-domains] [--no-extra] [--no-global] [--compose] [--dry-run] [--yes] [--force] [--refresh] [--clear-cache] [--version|-V] [--verbose|-v] [--quiet|-q] [--json] [--help|-h]
2
2
 
3
3
  Options:
4
4
  --help, -h Show help and exit
5
5
  --version, -V Show version and exit
6
6
  --verbose, -v Show verbose diagnostics
7
+ --quiet, -q Suppress non-error human-readable output (JSON output is not suppressed)
8
+ --json Output machine-readable JSON (takes precedence over --quiet)
7
9
  --root <path> Project root directory (default: current working directory)
8
10
  --ruleset <path> Only compose a single ruleset file
9
11
  --ruleset-name <name> Ruleset filename in the project root (default: agent-ruleset.json)