@softspark/ai-toolkit 1.4.1 → 1.4.2

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
@@ -7,6 +7,18 @@ Versioning follows [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ---
9
9
 
10
+ ## v1.4.2 — --local Scoping Fix, Leading Blank Lines Fix (2026-04-09)
11
+
12
+ ### Fixed
13
+ - `--local` now runs only project-local install (no global re-install). Global install runs separately without `--local`.
14
+ - Fixed leading blank lines in generated files (copilot-instructions.md, etc.) caused by `inject_section` and `inject_with_rules`.
15
+ - Context-aware "Next steps" message (local vs global).
16
+
17
+ ### Changed
18
+ - Updated KB docs: global-install-model.md, maintenance-sop.md to reflect `--local` scoping change.
19
+
20
+ ---
21
+
10
22
  ## v1.4.1 — Documentation Fix: --local Behavior (2026-04-09)
11
23
 
12
24
  ### Fixed
@@ -91,7 +91,7 @@ ai-toolkit update
91
91
 
92
92
  ```bash
93
93
  ai-toolkit update --only agents,hooks # re-apply only specific components
94
- ai-toolkit update --local # also refresh project-local Copilot + Cline + Roo + Aider
94
+ ai-toolkit update --local # refresh project-local configs (auto-detects editors from existing files)
95
95
  ai-toolkit update --list # dry-run: show what would change
96
96
  ```
97
97
 
@@ -23,8 +23,8 @@ That means one machine-level install provides agents, skills, hooks, and rules t
23
23
  |---------|--------|---------|
24
24
  | `ai-toolkit install` | `~/.claude/` | first-time machine setup |
25
25
  | `ai-toolkit update` | `~/.claude/` | re-apply after package or rule changes |
26
- | `ai-toolkit install --local` | current project | create local `CLAUDE.md`, `.claude/settings.local.json`, and inject constitution + Copilot + Cline + Roo Code + Aider configs. Installs git hooks fallback. |
27
- | `ai-toolkit update --local` | current project | refresh those local project files |
26
+ | `ai-toolkit install --local` | current project | Claude Code configs only (CLAUDE.md, settings, constitution, language rules). Add `--editors all` for other tools. |
27
+ | `ai-toolkit update --local` | current project | refresh project configs; auto-detects editors from existing files |
28
28
  | `ai-toolkit add-rule` | `~/.ai-toolkit/rules/` | register a global rule |
29
29
  | `ai-toolkit remove-rule` | `~/.ai-toolkit/rules/` | unregister a global rule |
30
30
 
package/manifest.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.4.1",
2
+ "version": "1.4.2",
3
3
  "components": {
4
4
  "agents": {
5
5
  "description": "44 specialized agents (orchestrator, backend, frontend, security, devops, etc.)",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softspark/ai-toolkit",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
4
4
  "description": "Professional-grade AI coding toolkit: 91 skills, 44 agents, multi-platform support (Claude, Cursor, Windsurf, Copilot, Gemini, Cline, Roo Code, Aider, Augment, Google Antigravity), machine-enforced safety constitution, persona presets, skill security auditor, expanded lifecycle hooks, 11 plugin packs, and benchmark tooling.",
5
5
  "keywords": [
6
6
  "claude",
@@ -134,6 +134,7 @@ def inject_section(
134
134
 
135
135
  output = "\n".join(parts) + "\n"
136
136
  output = collapse_blank_runs(output)
137
+ output = output.lstrip("\n") # no leading blank lines
137
138
 
138
139
  target_file.write_text(output, encoding="utf-8")
139
140
  return action
@@ -312,16 +312,23 @@ def print_banner(target_dir: Path, rules_dir: Path, profile: str,
312
312
  print()
313
313
 
314
314
 
315
- def print_summary() -> None:
315
+ def print_summary(local: bool = False) -> None:
316
316
  print()
317
317
  print("Done.")
318
- print()
319
- print("Next steps:")
320
- print(" 1. Edit ~/.claude/CLAUDE.md -- add your global rules above the toolkit sections")
321
- print(" 2. Per project: ai-toolkit install --local (or: ai-toolkit update --local)")
322
- print(" 3. To update: npm install -g @softspark/ai-toolkit@latest && ai-toolkit update")
323
- print(" 4. To register rules from other tools: ai-toolkit add-rule <rule.md>")
324
- print(" 5. Check install state: ai-toolkit status")
318
+ if local:
319
+ print()
320
+ print("Next steps:")
321
+ print(" 1. Edit CLAUDE.md -- add your project-specific rules")
322
+ print(" 2. Add more editors: ai-toolkit install --local --editors cursor,aider")
323
+ print(" 3. Update project configs: ai-toolkit update --local")
324
+ else:
325
+ print()
326
+ print("Next steps:")
327
+ print(" 1. Edit ~/.claude/CLAUDE.md -- add your global rules above the toolkit sections")
328
+ print(" 2. Per project: ai-toolkit install --local --editors all")
329
+ print(" 3. To update: npm install -g @softspark/ai-toolkit@latest && ai-toolkit update")
330
+ print(" 4. To register rules from other tools: ai-toolkit add-rule <rule.md>")
331
+ print(" 5. Check install state: ai-toolkit status")
325
332
 
326
333
 
327
334
  # ---------------------------------------------------------------------------
@@ -457,25 +464,26 @@ def main() -> None:
457
464
  only = resolve_profile(profile, only)
458
465
 
459
466
  check_dependencies()
460
- print_banner(target_dir, rules_dir, profile, only, skip, dry_run,
461
- modules=resolved_modules)
462
467
 
463
468
  if not dry_run:
464
469
  rules_dir.mkdir(parents=True, exist_ok=True)
465
470
  hooks_scripts_dir.mkdir(parents=True, exist_ok=True)
466
471
 
467
- install_claude_code(target_dir, hooks_scripts_dir, rules_dir, only, skip, dry_run)
468
- install_ai_tools(target_dir, rules_dir, only, skip, dry_run)
469
-
470
472
  if local:
471
- # Pass language modules for --auto-detect / --modules rules-*
473
+ # --local: project-local only, no global install
472
474
  lang_modules = [m for m in (resolved_modules or []) if m.startswith("rules-")]
473
475
  editors_arg: str = cfg["editors"]
474
476
  install_local_project(rules_dir, dry_run, reset, lang_modules or None,
475
477
  editors=editors_arg)
476
-
477
- install_persona(target_dir, persona, dry_run)
478
- install_strict_git_hooks(profile, local, dry_run)
478
+ install_strict_git_hooks(profile, local, dry_run)
479
+ else:
480
+ # Global install
481
+ print_banner(target_dir, rules_dir, profile, only, skip, dry_run,
482
+ modules=resolved_modules)
483
+ install_claude_code(target_dir, hooks_scripts_dir, rules_dir, only, skip, dry_run)
484
+ install_ai_tools(target_dir, rules_dir, only, skip, dry_run)
485
+ install_persona(target_dir, persona, dry_run)
486
+ install_strict_git_hooks(profile, local, dry_run)
479
487
 
480
488
  # Record install state (skip for dry-run)
481
489
  if not dry_run:
@@ -497,7 +505,7 @@ def main() -> None:
497
505
  auto_detected=auto_detected,
498
506
  )
499
507
 
500
- print_summary()
508
+ print_summary(local=local)
501
509
 
502
510
 
503
511
  def _infer_modules_from_legacy(profile: str, only: str) -> list[str]:
@@ -90,6 +90,7 @@ def inject_with_rules(
90
90
  if start_marker in existing:
91
91
  existing = _strip_section(existing, "ai-toolkit")
92
92
  existing = _trim_trailing_blanks(existing)
93
+ existing = existing.lstrip("\n") # no leading blank lines
93
94
 
94
95
  parts: list[str] = []
95
96
  if existing.strip():
@@ -99,6 +100,7 @@ def inject_with_rules(
99
100
 
100
101
  output = "\n".join(parts) + "\n"
101
102
  output = _collapse_blank_runs(output)
103
+ output = output.lstrip("\n") # no leading blank lines
102
104
  target_file.write_text(output, encoding="utf-8")
103
105
 
104
106
  if rules_dir.is_dir():