bundler-skills 0.1.0 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/README.md +17 -1
- data/lib/bundler_skills/command.rb +31 -1
- data/lib/bundler_skills/linker.rb +5 -0
- data/lib/bundler_skills/synchronizer.rb +34 -4
- data/lib/bundler_skills/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 439aafda99d985a5bd8da3676ad50a82f17d1e8bf01a895d193998ae1faf885d
|
|
4
|
+
data.tar.gz: 0050bcd8e99963aecc9b847bba9697e2b88b8d55ecee0f3c8d6a7340a6b0ad9c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: de83628fb2e88ab3388afd068d0c478eb901fac43df5858ca280af1012dfaa64363599a4e640874d3d8e392b4189dd7f3962420a0e44d458cb5c5893d6880409
|
|
7
|
+
data.tar.gz: 46029390766998a7ede9dc14546d6fbbff54810973196a8e8626ce653b905cbcd43dec302d63f1b21e88915c74703296d5ac22881dd9b3ac2e6930b14b3b29a0
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.3.0] - 2026-06-21
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Post-install summary now highlights runs that actually changed something:
|
|
10
|
+
when skills are created, relinked (after a gem update), or pruned, the summary
|
|
11
|
+
line is printed in green (`confirm`) instead of plain text, and the count of
|
|
12
|
+
relinked skills is now shown alongside linked/pruned.
|
|
13
|
+
- A changed run additionally lists each affected skill grouped by kind
|
|
14
|
+
(created / relinked / pruned), showing the path to its `SKILL.md`, so the
|
|
15
|
+
third-party skill contents linked into your project are easy to review.
|
|
16
|
+
|
|
17
|
+
## [0.2.0] - 2026-06-18
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- `bundle skills init` command: creates a `bundler-skills.yml` config file with
|
|
22
|
+
all keys commented out, so users can enable only the options they need.
|
|
23
|
+
|
|
5
24
|
## [0.1.0] - 2026-06-18
|
|
6
25
|
|
|
7
26
|
### Added
|
data/README.md
CHANGED
|
@@ -56,7 +56,22 @@ bundle install
|
|
|
56
56
|
That's it. On install you'll see something like:
|
|
57
57
|
|
|
58
58
|
```
|
|
59
|
-
[bundler-skills] 3 skill(s) discovered, 3 linked, 0 pruned across 1 dir(s) (agents: claude)
|
|
59
|
+
[bundler-skills] 3 skill(s) discovered, 3 linked, 0 relinked, 0 pruned across 1 dir(s) (agents: claude)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
When a run actually changes something (links created, relinked after a gem
|
|
63
|
+
update, or stale links pruned) the summary is printed in green so it stands out;
|
|
64
|
+
a run with nothing to do prints the same line in plain text. A changed run also
|
|
65
|
+
lists each affected skill, grouped by kind, with the path to its `SKILL.md` so
|
|
66
|
+
you can review the (third-party) skill contents now linked into your project:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
[bundler-skills] 3 skill(s) discovered, 2 linked, 1 relinked, 0 pruned across 1 dir(s) (agents: claude)
|
|
70
|
+
created:
|
|
71
|
+
.claude/skills/gem-rubocop--style -> /path/to/gems/rubocop/skills/style
|
|
72
|
+
.claude/skills/gem-rubocop--lint -> /path/to/gems/rubocop/skills/lint
|
|
73
|
+
relinked:
|
|
74
|
+
.claude/skills/gem-rspec--matchers -> /path/to/gems/rspec/skills/matchers
|
|
60
75
|
```
|
|
61
76
|
|
|
62
77
|
> Alternatively, install it globally with `bundle plugin install bundler-skills`.
|
|
@@ -72,6 +87,7 @@ Use the command to sync manually, or to inspect/clean:
|
|
|
72
87
|
bundle skills # (or: bundle skills sync) re-create symlinks
|
|
73
88
|
bundle skills list # show discovered skills and target agents (no changes)
|
|
74
89
|
bundle skills clean # remove all gem-*--* symlinks this plugin created
|
|
90
|
+
bundle skills init # create a bundler-skills.yml config file with defaults
|
|
75
91
|
bundle skills <cmd> --dry-run # show what would change without writing
|
|
76
92
|
```
|
|
77
93
|
|
|
@@ -9,14 +9,32 @@ module BundlerSkills
|
|
|
9
9
|
class Command < Bundler::Plugin::API
|
|
10
10
|
command "skills"
|
|
11
11
|
|
|
12
|
+
INIT_TEMPLATE = <<~YAML
|
|
13
|
+
# bundler-skills.yml — all keys are optional
|
|
14
|
+
#
|
|
15
|
+
# enabled: # nil (auto) | false (off) | [development] (env list)
|
|
16
|
+
# agents: # omit = auto-detect; or list: [claude, cursor]; or "*"
|
|
17
|
+
# - claude
|
|
18
|
+
# - cursor
|
|
19
|
+
# gitignore: true # manage .gitignore (default true)
|
|
20
|
+
# cleanup: true # prune stale gem-*--* links when a gem is removed (default true)
|
|
21
|
+
# recursive: false # also scan skills/**/SKILL.md (default false)
|
|
22
|
+
# include: # only these gems (empty = all). fnmatch on "gem" or "gem/skill"
|
|
23
|
+
# - rubocop
|
|
24
|
+
# - "rails-*"
|
|
25
|
+
# exclude: # exclude these (wins over include)
|
|
26
|
+
# - some-noisy-gem
|
|
27
|
+
YAML
|
|
28
|
+
|
|
12
29
|
def exec(_command_name, args)
|
|
13
|
-
dry_run = args.delete("--dry-run")
|
|
30
|
+
dry_run = !!args.delete("--dry-run")
|
|
14
31
|
subcommand = args.shift || "sync"
|
|
15
32
|
|
|
16
33
|
case subcommand
|
|
17
34
|
when "sync" then run_sync(dry_run)
|
|
18
35
|
when "list" then run_list
|
|
19
36
|
when "clean" then run_clean(dry_run)
|
|
37
|
+
when "init" then run_init
|
|
20
38
|
when "help", "-h", "--help" then print_help
|
|
21
39
|
else
|
|
22
40
|
Bundler.ui.error("[bundler-skills] unknown subcommand: #{subcommand}")
|
|
@@ -51,6 +69,17 @@ module BundlerSkills
|
|
|
51
69
|
end
|
|
52
70
|
end
|
|
53
71
|
|
|
72
|
+
def run_init
|
|
73
|
+
path = Bundler.root / Config::CONFIG_FILENAME
|
|
74
|
+
if File.exist?(path)
|
|
75
|
+
Bundler.ui.warn("[bundler-skills] #{Config::CONFIG_FILENAME} already exists")
|
|
76
|
+
return
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
File.write(path, INIT_TEMPLATE)
|
|
80
|
+
Bundler.ui.info("[bundler-skills] created #{Config::CONFIG_FILENAME}")
|
|
81
|
+
end
|
|
82
|
+
|
|
54
83
|
def run_clean(dry_run)
|
|
55
84
|
removed = synchronizer(dry_run: dry_run).clean
|
|
56
85
|
total = removed.values.sum(&:size)
|
|
@@ -68,6 +97,7 @@ module BundlerSkills
|
|
|
68
97
|
sync (default) discover skills and (re)create symlinks
|
|
69
98
|
list show discovered skills and target agents (no changes)
|
|
70
99
|
clean remove all gem-*--* symlinks this plugin created
|
|
100
|
+
init create a bundler-skills.yml config file with defaults
|
|
71
101
|
|
|
72
102
|
Options:
|
|
73
103
|
--dry-run show what would change without writing
|
|
@@ -22,6 +22,11 @@ module BundlerSkills
|
|
|
22
22
|
@skipped = []
|
|
23
23
|
@pruned = []
|
|
24
24
|
end
|
|
25
|
+
|
|
26
|
+
# Did this run actually mutate the filesystem? kept/skipped are no-ops.
|
|
27
|
+
def changed?
|
|
28
|
+
created.any? || relinked.any? || pruned.any?
|
|
29
|
+
end
|
|
25
30
|
end
|
|
26
31
|
|
|
27
32
|
def initialize(skills_dir:, config: Config.new(Config::DEFAULTS), logger: nil)
|
|
@@ -83,12 +83,42 @@ module BundlerSkills
|
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
created = links_by_dir.values.sum { |r| r.created.size }
|
|
86
|
+
relinked = links_by_dir.values.sum { |r| r.relinked.size }
|
|
86
87
|
pruned = links_by_dir.values.sum { |r| r.pruned.size }
|
|
87
|
-
|
|
88
|
+
|
|
89
|
+
message =
|
|
88
90
|
"[bundler-skills] #{skills.size} skill(s) discovered, " \
|
|
89
|
-
"#{created} linked, #{
|
|
90
|
-
"(agents: #{agents.map(&:key).join(', ')})"
|
|
91
|
-
|
|
91
|
+
"#{created} linked, #{relinked} relinked, #{pruned} pruned " \
|
|
92
|
+
"across #{links_by_dir.size} dir(s) (agents: #{agents.map(&:key).join(', ')})"
|
|
93
|
+
|
|
94
|
+
# Make a run that actually changed something stand out (green) so it is
|
|
95
|
+
# noticed amid bundle's output; an unchanged run stays plain.
|
|
96
|
+
if links_by_dir.values.any?(&:changed?)
|
|
97
|
+
@logger.confirm(message)
|
|
98
|
+
# List the skills that changed so the user can review the (third-party)
|
|
99
|
+
# SKILL.md contents now linked into their project. created/relinked are
|
|
100
|
+
# in the discovery set so we can show their source path; pruned skills
|
|
101
|
+
# are already gone, so we show the name only.
|
|
102
|
+
log_changed_skills(skills, links_by_dir)
|
|
103
|
+
else
|
|
104
|
+
@logger.info(message)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def log_changed_skills(skills, links_by_dir)
|
|
109
|
+
source_by_link = skills.to_h { |s| [s.link_name, s.source_path] }
|
|
110
|
+
|
|
111
|
+
%i[created relinked pruned].each do |kind|
|
|
112
|
+
entries = links_by_dir.flat_map do |subdir, result|
|
|
113
|
+
result.public_send(kind).map { |name| [File.join(subdir, name), source_by_link[name]] }
|
|
114
|
+
end
|
|
115
|
+
next if entries.empty?
|
|
116
|
+
|
|
117
|
+
@logger.info(" #{kind}:")
|
|
118
|
+
entries.each do |path, source|
|
|
119
|
+
@logger.info(source ? " #{path} -> #{source}" : " #{path}")
|
|
120
|
+
end
|
|
121
|
+
end
|
|
92
122
|
end
|
|
93
123
|
end
|
|
94
124
|
end
|